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