[PATCH v5 5/7] vbscript: Implement separate script dispatch objects for each named item.

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Feb 12 07:36:23 CST 2020


Each named item should have its own associated script dispatch
object. Identifiers are added to this object, but code does look into the
global script object as well.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---

v5: Create the script dispatch on demand in exec_global_code and in
lookup_named_item (needed by compilation and GetScriptDispatch before
executing any code).

 dlls/vbscript/compile.c  | 47 +++++++++++++++++++++++++--------------
 dlls/vbscript/interp.c   | 27 ++++++++++++++++------
 dlls/vbscript/vbscript.c | 48 +++++++++++++++++++++++++++++++++++++---
 dlls/vbscript/vbscript.h |  4 ++++
 4 files changed, 99 insertions(+), 27 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 9888109..8ce4692 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -1778,26 +1778,33 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
     return S_OK;
 }
 
-static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier)
+static BOOL lookup_script_identifier(compile_ctx_t *ctx, script_ctx_t *script, const WCHAR *identifier)
 {
-    ScriptDisp *obj = script->script_obj;
+    ScriptDisp *contexts[] = {
+        ctx->code->named_item ? ctx->code->named_item->script_obj : NULL,
+        script->script_obj
+    };
     class_desc_t *class;
     vbscode_t *code;
-    unsigned i;
+    unsigned c, i;
 
-    for(i = 0; i < obj->global_vars_cnt; i++) {
-        if(!wcsicmp(obj->global_vars[i]->name, identifier))
-            return TRUE;
-    }
+    for(c = 0; c < ARRAY_SIZE(contexts); c++) {
+        if(!contexts[c]) continue;
 
-    for(i = 0; i < obj->global_funcs_cnt; i++) {
-        if(!wcsicmp(obj->global_funcs[i]->name, identifier))
-            return TRUE;
-    }
+        for(i = 0; i < contexts[c]->global_vars_cnt; i++) {
+            if(!wcsicmp(contexts[c]->global_vars[i]->name, identifier))
+                return TRUE;
+        }
 
-    for(class = obj->classes; class; class = class->next) {
-        if(!wcsicmp(class->name, identifier))
-            return TRUE;
+        for(i = 0; i < contexts[c]->global_funcs_cnt; i++) {
+            if(!wcsicmp(contexts[c]->global_funcs[i]->name, identifier))
+                return TRUE;
+        }
+
+        for(class = contexts[c]->classes; class; class = class->next) {
+            if(!wcsicmp(class->name, identifier))
+                return TRUE;
+        }
     }
 
     LIST_FOR_EACH_ENTRY(code, &script->code_list, vbscode_t, entry) {
@@ -1805,7 +1812,7 @@ static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifi
         var_desc_t *vars = code->main_code.vars;
         function_t *func;
 
-        if(!code->pending_exec)
+        if(!code->pending_exec || (code->named_item && code->named_item != ctx->code->named_item))
             continue;
 
         for(i = 0; i < var_cnt; i++) {
@@ -1834,14 +1841,14 @@ static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
     class_desc_t *class;
 
     for(i = 0; i < var_cnt; i++) {
-        if(lookup_script_identifier(script, vars[i].name)) {
+        if(lookup_script_identifier(ctx, script, vars[i].name)) {
             FIXME("%s: redefined\n", debugstr_w(vars[i].name));
             return E_FAIL;
         }
     }
 
     for(class = ctx->code->classes; class; class = class->next) {
-        if(lookup_script_identifier(script, class->name)) {
+        if(lookup_script_identifier(ctx, script, class->name)) {
             FIXME("%s: redefined\n", debugstr_w(class->name));
             return E_FAIL;
         }
@@ -1862,6 +1869,8 @@ void release_vbscode(vbscode_t *code)
 
     if(code->context)
         IDispatch_Release(code->context);
+    if(code->named_item)
+        release_named_item(code->named_item);
     heap_pool_free(&code->heap);
 
     heap_free(code->bstr_pool);
@@ -1944,6 +1953,10 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item
     code = ctx.code = alloc_vbscode(&ctx, src, cookie, start_line);
     if(!ctx.code)
         return E_OUTOFMEMORY;
+    if(item) {
+        code->named_item = item;
+        item->ref++;
+    }
 
     hres = parse_script(&ctx.parser, code->source, delimiter, flags);
     if(FAILED(hres)) {
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index f0820be..4f5e463 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -191,6 +191,13 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
         }
     }
 
+    if(ctx->code->named_item) {
+        if(lookup_global_vars(ctx->code->named_item->script_obj, name, ref))
+            return S_OK;
+        if(lookup_global_funcs(ctx->code->named_item->script_obj, name, ref))
+            return S_OK;
+    }
+
     if(lookup_global_vars(script_obj, name, ref))
         return S_OK;
     if(lookup_global_funcs(script_obj, name, ref))
@@ -230,7 +237,7 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
 static HRESULT add_dynamic_var(exec_ctx_t *ctx, const WCHAR *name,
         BOOL is_const, VARIANT **out_var)
 {
-    ScriptDisp *script_obj = ctx->script->script_obj;
+    ScriptDisp *script_obj = ctx->code->named_item ? ctx->code->named_item->script_obj : ctx->script->script_obj;
     dynamic_var_t *new_var;
     heap_pool_t *heap;
     WCHAR *str;
@@ -1113,7 +1120,7 @@ static HRESULT interp_deref(exec_ctx_t *ctx)
 static HRESULT interp_new(exec_ctx_t *ctx)
 {
     const WCHAR *arg = ctx->instr->arg1.bstr;
-    class_desc_t *class_desc;
+    class_desc_t *class_desc = NULL;
     vbdisp_t *obj;
     VARIANT v;
     HRESULT hres;
@@ -1131,10 +1138,14 @@ static HRESULT interp_new(exec_ctx_t *ctx)
         return stack_push(ctx, &v);
     }
 
-    for(class_desc = ctx->script->script_obj->classes; class_desc; class_desc = class_desc->next) {
-        if(!wcsicmp(class_desc->name, arg))
-            break;
-    }
+    if(ctx->code->named_item)
+        for(class_desc = ctx->code->named_item->script_obj->classes; class_desc; class_desc = class_desc->next)
+            if(!wcsicmp(class_desc->name, arg))
+                break;
+    if(!class_desc)
+        for(class_desc = ctx->script->script_obj->classes; class_desc; class_desc = class_desc->next)
+            if(!wcsicmp(class_desc->name, arg))
+                break;
     if(!class_desc) {
         FIXME("Class %s not found\n", debugstr_w(arg));
         return E_FAIL;
@@ -1151,7 +1162,7 @@ static HRESULT interp_new(exec_ctx_t *ctx)
 
 static HRESULT interp_dim(exec_ctx_t *ctx)
 {
-    ScriptDisp *script_obj = ctx->script->script_obj;
+    ScriptDisp *script_obj = ctx->code->named_item ? ctx->code->named_item->script_obj : ctx->script->script_obj;
     const BSTR ident = ctx->instr->arg1.bstr;
     const unsigned array_id = ctx->instr->arg2.uint;
     const array_desc_t *array_desc;
@@ -1517,6 +1528,8 @@ static HRESULT interp_me(exec_ctx_t *ctx)
 
     if(ctx->vbthis)
         disp = (IDispatch*)&ctx->vbthis->IDispatchEx_iface;
+    else if(ctx->code->named_item)
+        disp = (IDispatch*)&ctx->code->named_item->script_obj->IDispatchEx_iface;
     else if(ctx->script->host_global)
         disp = ctx->script->host_global;
     else
diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c
index 670b66d..52dbd32 100644
--- a/dlls/vbscript/vbscript.c
+++ b/dlls/vbscript/vbscript.c
@@ -97,6 +97,15 @@ static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res
     function_t *func_iter, **new_funcs;
     dynamic_var_t *var, **new_vars;
     size_t cnt, i;
+    HRESULT hres;
+
+    if(code->named_item) {
+        if(!code->named_item->script_obj) {
+            hres = create_script_disp(ctx, &code->named_item->script_obj);
+            if(FAILED(hres)) return hres;
+        }
+        obj = code->named_item->script_obj;
+    }
 
     cnt = obj->global_vars_cnt + code->main_code.var_cnt;
     if (cnt > obj->global_vars_size)
@@ -197,6 +206,10 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned f
 
     LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) {
         if((item->flags & flags) == flags && !wcsicmp(item->name, name)) {
+            if(!item->script_obj) {
+                hres = create_script_disp(ctx, &item->script_obj);
+                if(FAILED(hres)) return NULL;
+            }
             if(!item->disp && !(item->flags & no_disp_flags)) {
                 IUnknown *unk;
 
@@ -222,6 +235,23 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned f
     return NULL;
 }
 
+static void release_named_item_script_obj(named_item_t *item)
+{
+    if(!item->script_obj) return;
+
+    item->script_obj->ctx = NULL;
+    IDispatchEx_Release(&item->script_obj->IDispatchEx_iface);
+    item->script_obj = NULL;
+}
+
+void release_named_item(named_item_t *item)
+{
+    if(--item->ref) return;
+
+    heap_free(item->name);
+    heap_free(item);
+}
+
 static void release_script(script_ctx_t *ctx)
 {
     vbscode_t *code, *code_next;
@@ -235,6 +265,7 @@ static void release_script(script_ctx_t *ctx)
         {
             code->pending_exec = TRUE;
             if(code->last_class) code->last_class->next = NULL;
+            if(code->named_item) release_named_item_script_obj(code->named_item);
         }
         else
         {
@@ -249,8 +280,8 @@ static void release_script(script_ctx_t *ctx)
         list_remove(&iter->entry);
         if(iter->disp)
             IDispatch_Release(iter->disp);
-        heap_free(iter->name);
-        heap_free(iter);
+        release_named_item_script_obj(iter);
+        release_named_item(iter);
     }
 
     if(ctx->host_global) {
@@ -659,8 +690,10 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr
         return E_OUTOFMEMORY;
     }
 
+    item->ref = 1;
     item->disp = disp;
     item->flags = dwFlags;
+    item->script_obj = NULL;
     item->name = heap_strdupW(pstrName);
     if(!item->name) {
         if(disp)
@@ -684,6 +717,7 @@ static HRESULT WINAPI VBScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTyp
 static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp)
 {
     VBScript *This = impl_from_IActiveScript(iface);
+    ScriptDisp *script_obj;
 
     TRACE("(%p)->(%s %p)\n", This, debugstr_w(pstrItemName), ppdisp);
 
@@ -695,7 +729,15 @@ static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR
         return E_UNEXPECTED;
     }
 
-    *ppdisp = (IDispatch*)&This->ctx->script_obj->IDispatchEx_iface;
+    if(pstrItemName) {
+        named_item_t *item = lookup_named_item(This->ctx, pstrItemName, 0);
+        if(!item) return E_INVALIDARG;
+        script_obj = item->script_obj;
+    }
+    else
+        script_obj = This->ctx->script_obj;
+
+    *ppdisp = (IDispatch*)&script_obj->IDispatchEx_iface;
     IDispatch_AddRef(*ppdisp);
     return S_OK;
 }
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 589abc3..5860863 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -149,7 +149,9 @@ typedef struct {
 } BuiltinDisp;
 
 typedef struct named_item_t {
+    ScriptDisp *script_obj;
     IDispatch *disp;
+    unsigned ref;
     DWORD flags;
     LPWSTR name;
 
@@ -349,6 +351,7 @@ struct _vbscode_t {
     BOOL is_persistent;
     function_t main_code;
     IDispatch *context;
+    named_item_t *named_item;
 
     BSTR *bstr_pool;
     unsigned bstr_pool_size;
@@ -373,6 +376,7 @@ HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,D
 HRESULT exec_script(script_ctx_t*,BOOL,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN;
 void release_dynamic_var(dynamic_var_t*) DECLSPEC_HIDDEN;
 named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN;
+void release_named_item(named_item_t*) DECLSPEC_HIDDEN;
 void clear_ei(EXCEPINFO*) DECLSPEC_HIDDEN;
 HRESULT report_script_error(script_ctx_t*,const vbscode_t*,unsigned) DECLSPEC_HIDDEN;
 void detach_global_objects(script_ctx_t*) DECLSPEC_HIDDEN;
-- 
2.21.0




More information about the wine-devel mailing list