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

Gabriel Ivăncescu gabrielopcode at gmail.com
Fri Feb 7 07:55:54 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>
---
 dlls/vbscript/compile.c  | 47 ++++++++++++++++++++++++--------------
 dlls/vbscript/interp.c   | 27 ++++++++++++++++------
 dlls/vbscript/vbscript.c | 49 +++++++++++++++++++++++++++++++++++++---
 dlls/vbscript/vbscript.h |  3 +++
 4 files changed, 99 insertions(+), 27 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index cd33641..07d27a8 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 && !--code->named_item->ref)
+        heap_free(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 adffc25..ff8949f 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 3b80fe8..1bba826 100644
--- a/dlls/vbscript/vbscript.c
+++ b/dlls/vbscript/vbscript.c
@@ -93,7 +93,7 @@ static inline BOOL is_started(VBScript *This)
 
 static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res)
 {
-    ScriptDisp *obj = ctx->script_obj;
+    ScriptDisp *obj = code->named_item ? code->named_item->script_obj : ctx->script_obj;
     function_t *func_iter, **new_funcs;
     dynamic_var_t *var, **new_vars;
     size_t cnt, i;
@@ -221,6 +221,15 @@ 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;
+}
+
 static void release_script(script_ctx_t *ctx)
 {
     vbscode_t *code, *code_next;
@@ -234,6 +243,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
         {
@@ -248,8 +258,10 @@ static void release_script(script_ctx_t *ctx)
         list_remove(&iter->entry);
         if(iter->disp)
             IDispatch_Release(iter->disp);
+        release_named_item_script_obj(iter);
         heap_free(iter->name);
-        heap_free(iter);
+        if(!--iter->ref)
+            heap_free(iter);
     }
 
     if(ctx->host_global) {
@@ -504,6 +516,7 @@ static ULONG WINAPI VBScript_Release(IActiveScript *iface)
 static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScriptSite *pass)
 {
     VBScript *This = impl_from_IActiveScript(iface);
+    vbscode_t *code;
     LCID lcid;
     HRESULT hres;
 
@@ -522,6 +535,21 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript
     if(FAILED(hres))
         return hres;
 
+    /* Create new script dispatches for persistent code with named items */
+    LIST_FOR_EACH_ENTRY(code, &This->ctx->code_list, vbscode_t, entry)
+    {
+        if(code->named_item && !code->named_item->script_obj)
+        {
+            hres = create_script_disp(This->ctx, &code->named_item->script_obj);
+            if(FAILED(hres))
+            {
+                This->ctx->script_obj->ctx = NULL;
+                IDispatchEx_Release(&This->ctx->script_obj->IDispatchEx_iface);
+                return hres;
+            }
+        }
+    }
+
     This->ctx->site = pass;
     IActiveScriptSite_AddRef(This->ctx->site);
 
@@ -659,8 +687,14 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr
     }
 
     item->disp = disp;
+    item->ref = 1;
     item->flags = dwFlags;
     item->name = heap_strdupW(pstrName);
+    hres = create_script_disp(This->ctx, &item->script_obj);
+    if(FAILED(hres)) {
+        heap_free(item->name);
+        item->name = NULL;
+    }
     if(!item->name) {
         if(disp)
             IDispatch_Release(disp);
@@ -683,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);
 
@@ -694,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, SCRIPTITEM_CODEONLY);
+        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 941834c..2f58807 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;
-- 
2.21.0




More information about the wine-devel mailing list