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

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Feb 5 10:38:46 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  | 44 ++++++++++++++++++++++++---------------
 dlls/vbscript/interp.c   | 29 +++++++++++++++++++-------
 dlls/vbscript/vbscript.c | 45 +++++++++++++++++++++++++++++++++++++---
 dlls/vbscript/vbscript.h |  2 ++
 4 files changed, 92 insertions(+), 28 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 9888109..faaa6be 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -1778,26 +1778,30 @@ 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->context_obj, 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 +1809,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->context_obj && code->context_obj != ctx->code->context_obj))
             continue;
 
         for(i = 0; i < var_cnt; i++) {
@@ -1834,14 +1838,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 +1866,8 @@ void release_vbscode(vbscode_t *code)
 
     if(code->context)
         IDispatch_Release(code->context);
+    if(code->context_obj)
+        IDispatchEx_Release(&code->context_obj->IDispatchEx_iface);
     heap_pool_free(&code->heap);
 
     heap_free(code->bstr_pool);
@@ -1944,6 +1950,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->context_obj = item->script_obj;
+        IDispatchEx_AddRef(&code->context_obj->IDispatchEx_iface);
+    }
 
     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..7ff3111 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->context_obj) {
+        if(lookup_global_vars(ctx->code->context_obj, name, ref))
+            return S_OK;
+        if(lookup_global_funcs(ctx->code->context_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->context_obj ? ctx->code->context_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->context_obj)
+        for(class_desc = ctx->code->context_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->context_obj ? ctx->code->context_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;
@@ -1520,7 +1531,9 @@ static HRESULT interp_me(exec_ctx_t *ctx)
     else if(ctx->script->host_global)
         disp = ctx->script->host_global;
     else
-        disp = (IDispatch*)&ctx->script->script_obj->IDispatchEx_iface;
+        disp = ctx->code->context_obj
+               ? (IDispatch*)&ctx->code->context_obj->IDispatchEx_iface
+               : (IDispatch*)&ctx->script->script_obj->IDispatchEx_iface;
 
     IDispatch_AddRef(disp);
     V_VT(&v) = VT_DISPATCH;
diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c
index 88574fe..15dde7c 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->context_obj ? code->context_obj : ctx->script_obj;
     function_t *func_iter, **new_funcs;
     dynamic_var_t *var, **new_vars;
     size_t cnt, i;
@@ -196,7 +196,7 @@ 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->disp) {
+            if(!item->disp && !(item->flags & SCRIPTITEM_CODEONLY)) {
                 IUnknown *unk;
 
                 hres = IActiveScriptSite_GetItemInfo(ctx->site, item->name,
@@ -234,6 +234,7 @@ static void release_script(script_ctx_t *ctx)
         {
             code->pending_exec = TRUE;
             if(code->last_class) code->last_class->next = NULL;
+            if(code->context_obj) code->context_obj->ctx = NULL;
         }
         else
         {
@@ -248,6 +249,8 @@ static void release_script(script_ctx_t *ctx)
         list_remove(&iter->entry);
         if(iter->disp)
             IDispatch_Release(iter->disp);
+        iter->script_obj->ctx = NULL;
+        IDispatchEx_Release(&iter->script_obj->IDispatchEx_iface);
         heap_free(iter->name);
         heap_free(iter);
     }
@@ -504,6 +507,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 +526,27 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript
     if(FAILED(hres))
         return hres;
 
+    /* Create fresh script dispatches for persistent code contexts */
+    LIST_FOR_EACH_ENTRY(code, &This->ctx->code_list, vbscode_t, entry)
+    {
+        if(code->context_obj)
+        {
+            ScriptDisp *disp;
+
+            hres = create_script_disp(This->ctx, &disp);
+            if(FAILED(hres))
+            {
+                This->ctx->script_obj->ctx = NULL;
+                IDispatchEx_Release(&This->ctx->script_obj->IDispatchEx_iface);
+                return hres;
+            }
+
+            code->context_obj->ctx = NULL;
+            IDispatchEx_Release(&code->context_obj->IDispatchEx_iface);
+            code->context_obj = disp;
+        }
+    }
+
     This->ctx->site = pass;
     IActiveScriptSite_AddRef(This->ctx->site);
 
@@ -661,6 +686,11 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr
     item->disp = disp;
     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 +713,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 +725,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..885e065 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -152,6 +152,7 @@ typedef struct named_item_t {
     IDispatch *disp;
     DWORD flags;
     LPWSTR name;
+    ScriptDisp *script_obj;
 
     struct list entry;
 } named_item_t;
@@ -349,6 +350,7 @@ struct _vbscode_t {
     BOOL is_persistent;
     function_t main_code;
     IDispatch *context;
+    ScriptDisp *context_obj;
 
     BSTR *bstr_pool;
     unsigned bstr_pool_size;
-- 
2.21.0




More information about the wine-devel mailing list