From 16fe2037fb2b3ddec1e6312b076cc76d88e9240a Mon Sep 17 00:00:00 2001 From: Robert Wilhelm Date: Tue, 13 Oct 2020 18:58:21 +0200 Subject: [PATCH] vbscript: Support class default sub. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35744 Signed-off-by: Robert Wilhelm Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/vbscript/compile.c | 14 +++++++++++--- dlls/vbscript/parser.y | 2 +- dlls/vbscript/tests/lang.vbs | 30 ++++++++++++++++++++++++++++++ dlls/vbscript/vbdisp.c | 6 ++---- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index e9f6361aee9..5c298ebe99a 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -1668,6 +1668,7 @@ static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name) static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) { function_decl_t *func_decl, *func_prop_decl; + BOOL is_default, have_default = FALSE; class_desc_t *class_desc; dim_decl_t *prop_decl; unsigned i; @@ -1690,14 +1691,21 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) if(!class_desc->name) return E_OUTOFMEMORY; - class_desc->func_cnt = 1; /* always allocate slot for default getter */ + class_desc->func_cnt = 1; /* always allocate slot for default getter or method */ for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) { + is_default = FALSE; for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) { - if(func_prop_decl->is_default) + if(func_prop_decl->is_default) { + if(have_default) { + FIXME("multiple default getters or methods\n"); + return E_FAIL; + } + is_default = have_default = TRUE; break; + } } - if(!func_prop_decl) + if(!is_default) class_desc->func_cnt++; } diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index 7e6cc17efd6..942e76459c2 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -993,7 +993,7 @@ static function_decl_t *new_function_decl(parser_ctx_t *ctx, const WCHAR *name, BOOL is_default = FALSE; if(storage_flags & STORAGE_IS_DEFAULT) { - if(type == FUNC_PROPGET) { + if(type == FUNC_PROPGET || type == FUNC_FUNCTION || type == FUNC_SUB) { is_default = TRUE; }else { FIXME("Invalid default property\n"); diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index fc762450a3b..65f8a458cd7 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -1750,6 +1750,36 @@ call ok(x.getprop.getprop().prop is obj, "x.getprop.getprop().prop is not obj (e ok getVT(x) = "VT_DISPATCH*", "getVT(x) = " & getVT(x) todo_wine_ok getVT(x()) = "VT_BSTR", "getVT(x()) = " & getVT(x()) +funcCalled = "" +class DefaultSubTest1 + Public default Sub init(a) + funcCalled = "init" & a + end sub +end class + +Set obj = New DefaultSubTest1 +obj.init(1) +call ok(funcCalled = "init1","funcCalled=" & funcCalled) +funcCalled = "" +obj(2) +call ok(funcCalled = "init2","funcCalled=" & funcCalled) + +class DefaultSubTest2 + Public Default Function init + funcCalled = "init" + end function +end class + +Set obj = New DefaultSubTest2 +funcCalled = "" +obj.init() +call ok(funcCalled = "init","funcCalled=" & funcCalled) +funcCalled = "" +' todo this is not yet supported +'funcCalled = "" +'obj() +'call ok(funcCalled = "init","funcCalled=" & funcCalled) + with nothing end with diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 1ff1110e56b..5f493d420bd 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -38,19 +38,17 @@ static BOOL get_func_id(vbdisp_t *This, const WCHAR *name, vbdisp_invoke_type_t { unsigned i; - for(i = invoke_type == VBDISP_ANY ? 0 : 1; i < This->desc->func_cnt; i++) { + for(i = 0; 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(!wcsicmp(This->desc->funcs[i].name, name)) { + if(This->desc->funcs[i].name && !wcsicmp(This->desc->funcs[i].name, name)) { *id = i; return TRUE; }