Jacek Caban : vbscript: Added compiler/runtime support for property getters /letters.

Alexandre Julliard julliard at winehq.org
Fri Sep 16 13:28:32 CDT 2011


Module: wine
Branch: master
Commit: 097a75f6744273a37bcb08d6fde71a2cafd882d5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=097a75f6744273a37bcb08d6fde71a2cafd882d5

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Sep 16 13:28:18 2011 +0200

vbscript: Added compiler/runtime support for property getters/letters.

---

 dlls/vbscript/compile.c      |   34 ++++++++++++++++++++++++---
 dlls/vbscript/interp.c       |   13 +++++-----
 dlls/vbscript/tests/lang.vbs |    8 ++++++
 dlls/vbscript/vbdisp.c       |   52 +++++++++++++++++++++++++++++++++---------
 dlls/vbscript/vbscript.h     |    2 +-
 5 files changed, 87 insertions(+), 22 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 015e775..6c30a40 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -813,16 +813,42 @@ static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name)
 
 static HRESULT create_class_funcprop(compile_ctx_t *ctx, function_decl_t *func_decl, vbdisp_funcprop_desc_t *desc)
 {
+    vbdisp_invoke_type_t invoke_type;
+    function_decl_t *funcprop_decl;
+    HRESULT hres;
+
     desc->name = compiler_alloc_string(ctx->code, func_decl->name);
     if(!desc->name)
         return E_OUTOFMEMORY;
 
-    assert(!desc->entries[0]);
+    for(funcprop_decl = func_decl; funcprop_decl; funcprop_decl = funcprop_decl->next_prop_func) {
+        switch(funcprop_decl->type) {
+        case FUNC_FUNCTION:
+        case FUNC_SUB:
+        case FUNC_PROPGET:
+            invoke_type = VBDISP_CALLGET;
+            break;
+        case FUNC_PROPLET:
+            invoke_type = VBDISP_LET;
+            break;
+        case FUNC_PROPSET:
+            invoke_type = VBDISP_SET;
+            break;
+        default:
+            assert(0);
+        }
 
-    if(func_decl->is_public)
-        desc->is_public = TRUE;
+        assert(!desc->entries[invoke_type]);
 
-    return create_function(ctx, func_decl, desc->entries);
+        if(funcprop_decl->is_public)
+            desc->is_public = TRUE;
+
+        hres = create_function(ctx, funcprop_decl, desc->entries+invoke_type);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    return S_OK;
 }
 
 static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index 27da9d3..7376d93 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -92,7 +92,8 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
     DISPID id;
     HRESULT hres;
 
-    if(invoke_type == VBDISP_LET && ctx->func->type == FUNC_FUNCTION && !strcmpiW(name, ctx->func->name)) {
+    if(invoke_type == VBDISP_LET && (ctx->func->type == FUNC_FUNCTION || ctx->func->type == FUNC_PROPGET)
+            && !strcmpiW(name, ctx->func->name)) {
         ref->type = REF_VAR;
         ref->u.v = &ctx->ret_val;
         return S_OK;
@@ -114,7 +115,7 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
         }
     }
 
-    hres = disp_get_id(ctx->this_obj, name, TRUE, &id);
+    hres = disp_get_id(ctx->this_obj, name, invoke_type, TRUE, &id);
     if(SUCCEEDED(hres)) {
         ref->type = REF_DISP;
         ref->u.d.disp = ctx->this_obj;
@@ -135,7 +136,7 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
 
     LIST_FOR_EACH_ENTRY(item, &ctx->script->named_items, named_item_t, entry) {
         if((item->flags & SCRIPTITEM_GLOBALMEMBERS) && item->disp != ctx->this_obj) {
-            hres = disp_get_id(item->disp, name, FALSE, &id);
+            hres = disp_get_id(item->disp, name, invoke_type, FALSE, &id);
             if(SUCCEEDED(hres)) {
                 ref->type = REF_DISP;
                 ref->u.d.disp = item->disp;
@@ -356,7 +357,7 @@ static HRESULT do_mcall(exec_ctx_t *ctx, VARIANT *res)
 
     vbstack_to_dp(ctx, arg_cnt, &dp);
 
-    hres = disp_get_id(obj, identifier, FALSE, &id);
+    hres = disp_get_id(obj, identifier, VBDISP_CALLGET, FALSE, &id);
     if(SUCCEEDED(hres))
         hres = disp_call(ctx->script, obj, id, &dp, res);
     IDispatch_Release(obj);
@@ -489,7 +490,7 @@ static HRESULT interp_assign_member(exec_ctx_t *ctx)
         return hres;
     }
 
-    hres = disp_get_id(obj, identifier, FALSE, &id);
+    hres = disp_get_id(obj, identifier, VBDISP_LET, FALSE, &id);
     if(SUCCEEDED(hres))
         hres = disp_propput(ctx->script, obj, id, val.v);
 
@@ -1204,7 +1205,7 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func, IDispatch *this_obj, DI
     }
 
     assert(!exec.top);
-    if(func->type != FUNC_FUNCTION)
+    if(func->type != FUNC_FUNCTION && func->type != FUNC_PROPGET)
         assert(V_VT(&exec.ret_val) == VT_EMPTY);
 
     if(SUCCEEDED(hres) && res) {
diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs
index ac70b5f..2a1bbb0 100644
--- a/dlls/vbscript/tests/lang.vbs
+++ b/dlls/vbscript/tests/lang.vbs
@@ -449,4 +449,12 @@ obj.publicProp() = 3
 Call obj.setPrivateProp(6)
 Call ok(obj.getPrivateProp = 6, "obj.getPrivateProp = " & obj.getPrivateProp)
 
+Dim funcCalled
+funcCalled = ""
+Call ok(obj.gsProp = 6, "obj.gsProp = " & obj.gsProp)
+Call ok(funcCalled = "gsProp get", "funcCalled = " & funcCalled)
+obj.gsProp = 3
+Call ok(funcCalled = "gsProp let", "funcCalled = " & funcCalled)
+Call ok(obj.getPrivateProp = 3, "obj.getPrivateProp = " & obj.getPrivateProp)
+
 reportSuccess()
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c
index e9bcb2a..a5fa63c 100644
--- a/dlls/vbscript/vbdisp.c
+++ b/dlls/vbscript/vbdisp.c
@@ -27,15 +27,21 @@ static inline BOOL is_func_id(vbdisp_t *This, DISPID id)
     return id < This->desc->func_cnt;
 }
 
-static BOOL get_func_id(vbdisp_t *This, const WCHAR *name, BOOL search_private, DISPID *id)
+static BOOL get_func_id(vbdisp_t *This, const WCHAR *name, vbdisp_invoke_type_t invoke_type, BOOL search_private, DISPID *id)
 {
     unsigned i;
 
-    for(i = 0; i < This->desc->func_cnt; i++) {
-        if(!search_private && !This->desc->funcs[i].is_public)
-            continue;
-        if(!This->desc->funcs[i].name) /* default value may not exist */
-            continue;
+    for(i = invoke_type == VBDISP_ANY ? 0 : 1; i < This->desc->func_cnt; i++) {
+        if(invoke_type == VBDISP_ANY) {
+            if(!search_private && !This->desc->funcs[i].is_public)
+                continue;
+            if(!i && !This->desc->funcs[0].name) /* default value may not exist */
+                continue;
+        }else {
+            if(!This->desc->funcs[i].entries[invoke_type]
+                || (!search_private && !This->desc->funcs[i].entries[invoke_type]->is_public))
+                continue;
+        }
 
         if(!strcmpiW(This->desc->funcs[i].name, name)) {
             *id = i;
@@ -46,11 +52,11 @@ static BOOL get_func_id(vbdisp_t *This, const WCHAR *name, BOOL search_private,
     return FALSE;
 }
 
-HRESULT vbdisp_get_id(vbdisp_t *This, BSTR name, BOOL search_private, DISPID *id)
+HRESULT vbdisp_get_id(vbdisp_t *This, BSTR name, vbdisp_invoke_type_t invoke_type, BOOL search_private, DISPID *id)
 {
     unsigned i;
 
-    if(get_func_id(This, name, search_private, id))
+    if(get_func_id(This, name, invoke_type, search_private, id))
         return S_OK;
 
     for(i=0; i < This->desc->prop_cnt; i++) {
@@ -225,7 +231,7 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
         return E_NOTIMPL;
     }
 
-    return vbdisp_get_id(This, bstrName, FALSE, pid);
+    return vbdisp_get_id(This, bstrName, VBDISP_ANY, FALSE, pid);
 }
 
 static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
@@ -254,6 +260,30 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
             }
 
             return exec_script(This->desc->ctx, func, (IDispatch*)&This->IDispatchEx_iface, pdp, pvarRes);
+        case DISPATCH_PROPERTYPUT: {
+            VARIANT *put_val;
+            DISPPARAMS dp = {NULL, NULL, 1, 0};
+
+            if(arg_cnt(pdp)) {
+                FIXME("arguments not implemented\n");
+                return E_NOTIMPL;
+            }
+
+            put_val = get_propput_arg(pdp);
+            if(!put_val) {
+                WARN("no value to set\n");
+                return DISP_E_PARAMNOTOPTIONAL;
+            }
+
+            dp.rgvarg = put_val;
+            func = This->desc->funcs[id].entries[V_VT(put_val) == VT_DISPATCH ? VBDISP_SET : VBDISP_LET];
+            if(!func) {
+                FIXME("no letter/setter\n");
+                return DISP_E_MEMBERNOTFOUND;
+            }
+
+            return exec_script(This->desc->ctx, func, (IDispatch*)&This->IDispatchEx_iface, &dp, NULL);
+        }
         default:
             FIXME("flags %x\n", wFlags);
             return DISP_E_MEMBERNOTFOUND;
@@ -355,7 +385,7 @@ HRESULT init_global(script_ctx_t *ctx)
     return create_vbdisp(&ctx->script_desc, &ctx->script_obj);
 }
 
-HRESULT disp_get_id(IDispatch *disp, BSTR name, BOOL search_private, DISPID *id)
+HRESULT disp_get_id(IDispatch *disp, BSTR name, vbdisp_invoke_type_t invoke_type, BOOL search_private, DISPID *id)
 {
     IDispatchEx *dispex;
     vbdisp_t *vbdisp;
@@ -363,7 +393,7 @@ HRESULT disp_get_id(IDispatch *disp, BSTR name, BOOL search_private, DISPID *id)
 
     vbdisp = unsafe_impl_from_IDispatch(disp);
     if(vbdisp)
-        return vbdisp_get_id(vbdisp, name, search_private, id);
+        return vbdisp_get_id(vbdisp, name, invoke_type, search_private, id);
 
     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
     if(FAILED(hres)) {
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 7433293..37fc7dd 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -93,7 +93,7 @@ typedef struct {
 } vbdisp_t;
 
 HRESULT create_vbdisp(const class_desc_t*,vbdisp_t**);
-HRESULT disp_get_id(IDispatch*,BSTR,BOOL,DISPID*);
+HRESULT disp_get_id(IDispatch*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*);
 HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,DISPPARAMS*,VARIANT*);
 HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,VARIANT*);
 




More information about the wine-cvs mailing list