Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35744 Signed-off-by: Robert Wilhelm robert.wilhelm@gmx.net --- dlls/vbscript/compile.c | 37 +++++++++++++++++++++++++++--------- dlls/vbscript/interp.c | 2 +- dlls/vbscript/parser.y | 4 ++++ dlls/vbscript/tests/lang.vbs | 31 ++++++++++++++++++++++++++++++ dlls/vbscript/vbdisp.c | 2 +- dlls/vbscript/vbscript.h | 4 +++- 6 files changed, 68 insertions(+), 12 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 2e991b0c0ae..d0342a128b1 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -1456,11 +1456,13 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
switch(func->type) { case FUNC_FUNCTION: + case FUNC_DEFFUNC: ctx->func_end_label = alloc_label(ctx); if(!ctx->func_end_label) return E_OUTOFMEMORY; break; case FUNC_SUB: + case FUNC_DEFSUB: ctx->sub_end_label = alloc_label(ctx); if(!ctx->sub_end_label) return E_OUTOFMEMORY; @@ -1628,7 +1630,9 @@ static HRESULT create_class_funcprop(compile_ctx_t *ctx, function_decl_t *func_d for(funcprop_decl = func_decl; funcprop_decl; funcprop_decl = funcprop_decl->next_prop_func) { switch(funcprop_decl->type) { case FUNC_FUNCTION: + case FUNC_DEFFUNC: case FUNC_SUB: + case FUNC_DEFSUB: case FUNC_PROPGET: case FUNC_DEFGET: invoke_type = VBDISP_CALLGET; @@ -1673,6 +1677,7 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) class_desc_t *class_desc; dim_decl_t *prop_decl; unsigned i; + BOOL isDefault=FALSE; HRESULT hres;
static const WCHAR class_initializeW[] = {'c','l','a','s','s','_','i','n','i','t','i','a','l','i','z','e',0}; @@ -1695,11 +1700,18 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) class_desc->func_cnt = 1; /* always allocate slot for default getter */
for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) { - for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) { - if(func_prop_decl->type == FUNC_DEFGET) - break; + isDefault = FALSE; + if(func_decl->type == FUNC_DEFFUNC || func_decl->type == FUNC_DEFSUB) { + isDefault = TRUE; + } else { + for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) { + if(func_prop_decl->type == FUNC_DEFGET) { + isDefault = TRUE; + break; + } + } } - if(!func_prop_decl) + if(isDefault != TRUE) class_desc->func_cnt++; }
@@ -1709,10 +1721,17 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) memset(class_desc->funcs, 0, class_desc->func_cnt*sizeof(*class_desc->funcs));
for(func_decl = class_decl->funcs, i=1; func_decl; func_decl = func_decl->next, i++) { - for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) { - if(func_prop_decl->type == FUNC_DEFGET) { - i--; - break; + isDefault = FALSE; + if(func_decl->type == FUNC_DEFFUNC || func_decl->type == FUNC_DEFSUB) { + i--; + isDefault = TRUE; + } else { + for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) { + if(func_prop_decl->type == FUNC_DEFGET) { + i--; + isDefault = TRUE; + break; + } } }
@@ -1732,7 +1751,7 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) class_desc->class_terminate_id = i; }
- hres = create_class_funcprop(ctx, func_decl, class_desc->funcs + (func_prop_decl ? 0 : i)); + hres = create_class_funcprop(ctx, func_decl, class_desc->funcs + (isDefault ? 0 : i)); if(FAILED(hres)) return hres; } diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index d58e89b7dba..51395f3c690 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -134,7 +134,7 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_ DISPID id; HRESULT hres;
- if((ctx->func->type == FUNC_FUNCTION || ctx->func->type == FUNC_PROPGET || ctx->func->type == FUNC_DEFGET) + if((ctx->func->type == FUNC_FUNCTION || ctx->func->type == FUNC_DEFFUNC || ctx->func->type == FUNC_PROPGET || ctx->func->type == FUNC_DEFGET) && !wcsicmp(name, ctx->func->name)) { ref->type = REF_VAR; ref->u.v = &ctx->ret_val; diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index cf94bdce464..9471f54bc2f 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -994,6 +994,10 @@ static function_decl_t *new_function_decl(parser_ctx_t *ctx, const WCHAR *name, if(storage_flags & STORAGE_IS_DEFAULT) { if(type == FUNC_PROPGET) { type = FUNC_DEFGET; + }else if(type == FUNC_FUNCTION) { + type = FUNC_DEFFUNC; + }else if(type == FUNC_SUB) { + type = FUNC_DEFSUB; }else { FIXME("Invalid default property\n"); ctx->hres = E_FAIL; diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index fc762450a3b..3250f889808 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -1750,6 +1750,37 @@ 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 36eba21e279..5178949e956 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -38,7 +38,7 @@ 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; diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 869fb05b6ed..1f4132b1898 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -314,7 +314,9 @@ typedef enum { FUNC_PROPGET, FUNC_PROPLET, FUNC_PROPSET, - FUNC_DEFGET + FUNC_DEFGET, + FUNC_DEFFUNC, + FUNC_DEFSUB } function_type_t;
typedef struct { -- 2.26.2
Hi Robert,
On 06.10.2020 23:14, Robert Wilhelm wrote:
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 869fb05b6ed..1f4132b1898 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -314,7 +314,9 @@ typedef enum { FUNC_PROPGET, FUNC_PROPLET, FUNC_PROPSET,
- FUNC_DEFGET
- FUNC_DEFGET,
- FUNC_DEFFUNC,
- FUNC_DEFSUB } function_type_t;
With your patch, 'default' is no longer a separated function type but rather a function flag. I'd expect that if you express that in data types, the implementation will be more straightforward. I'd suggest to get rid of FUNC_DEFGET and store the information about 'default' in function_decl_t (something like a new is_default flag or change is_public to (public,private,default) enum; I'm not sure without trying).
Is it possible to have both default getter and sub/function in the same class? Some tests around that would be interesting.
Thanks,
Jacek
Hi Jacek,
thanks for your suggestions. I will try using an is_default flag, this should result in cleaner code.
It is not allowed to have default getter and function and sub in one class. With native vbscript.dll I get: "Microsoft VBScript compilation error: Cannot have multiple default property/method in a Class" Therefore it should be save to use index 0 for default getter or function/sub. Currently we assert and crash when defining two default getters. I will add an FIXME.
Best regards, Robert
On Thu, 2020-10-08 at 15:56 +0200, Jacek Caban wrote:
Hi Robert,
On 06.10.2020 23:14, Robert Wilhelm wrote:
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 869fb05b6ed..1f4132b1898 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -314,7 +314,9 @@ typedef enum { FUNC_PROPGET, FUNC_PROPLET, FUNC_PROPSET,
- FUNC_DEFGET
- FUNC_DEFGET,
- FUNC_DEFFUNC,
- FUNC_DEFSUB } function_type_t;
With your patch, 'default' is no longer a separated function type but rather a function flag. I'd expect that if you express that in data types, the implementation will be more straightforward. I'd suggest to get rid of FUNC_DEFGET and store the information about 'default' in function_decl_t (something like a new is_default flag or change is_public to (public,private,default) enum; I'm not sure without trying).
Is it possible to have both default getter and sub/function in the same class? Some tests around that would be interesting.
Thanks,
Jacek