[PATCH] vbscript: support for class default sub.

Robert Wilhelm robert.wilhelm at gmx.net
Tue Oct 6 16:14:02 CDT 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35744
Signed-off-by: Robert Wilhelm <robert.wilhelm at 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





More information about the wine-devel mailing list