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

Gabriel Ivăncescu gabrielopcode at gmail.com
Fri Jan 31 07:29:01 CST 2020


Each named item should have its own associated script dispatch object. The
default object is special, though, because it's the only one that is reset
when the code is persistent (the others become dummies).

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

Tests in next patch will demonstrate this behavior.

 dlls/vbscript/compile.c  | 12 +++++++-----
 dlls/vbscript/interp.c   | 10 +++++-----
 dlls/vbscript/vbscript.c | 38 +++++++++++++++++++++++++++++++++++---
 dlls/vbscript/vbscript.h |  2 ++
 4 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 9888109..a7e82ad 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -1778,9 +1778,8 @@ 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(script_ctx_t *script, ScriptDisp *obj, const WCHAR *identifier)
 {
-    ScriptDisp *obj = script->script_obj;
     class_desc_t *class;
     vbscode_t *code;
     unsigned i;
@@ -1805,7 +1804,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->script_obj != obj)
             continue;
 
         for(i = 0; i < var_cnt; i++) {
@@ -1831,17 +1830,18 @@ static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
 {
     unsigned i, var_cnt = ctx->code->main_code.var_cnt;
     var_desc_t *vars = ctx->code->main_code.vars;
+    ScriptDisp *obj = ctx->code->script_obj;
     class_desc_t *class;
 
     for(i = 0; i < var_cnt; i++) {
-        if(lookup_script_identifier(script, vars[i].name)) {
+        if(lookup_script_identifier(script, obj, 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(script, obj, class->name)) {
             FIXME("%s: redefined\n", debugstr_w(class->name));
             return E_FAIL;
         }
@@ -1945,6 +1945,8 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item
     if(!ctx.code)
         return E_OUTOFMEMORY;
 
+    code->script_obj = item ? item->script_obj : script->script_obj;
+
     hres = parse_script(&ctx.parser, code->source, delimiter, flags);
     if(FAILED(hres)) {
         if(ctx.parser.error_loc != -1)
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index b328674..8ded5cd 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -112,7 +112,7 @@ static BOOL lookup_global_vars(ScriptDisp *script, const WCHAR *name, ref_t *ref
 
 static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_t invoke_type, ref_t *ref)
 {
-    ScriptDisp *script_obj = ctx->script->script_obj;
+    ScriptDisp *script_obj = ctx->code->script_obj;
     named_item_t *item;
     unsigned i;
     DISPID id;
@@ -221,7 +221,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->script_obj;
     dynamic_var_t *new_var;
     heap_pool_t *heap;
     WCHAR *str;
@@ -1122,7 +1122,7 @@ 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) {
+    for(class_desc = ctx->code->script_obj->classes; class_desc; class_desc = class_desc->next) {
         if(!wcsicmp(class_desc->name, arg))
             break;
     }
@@ -1142,7 +1142,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->script_obj;
     const BSTR ident = ctx->instr->arg1.bstr;
     const unsigned array_id = ctx->instr->arg2.uint;
     const array_desc_t *array_desc;
@@ -1511,7 +1511,7 @@ 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 = (IDispatch*)&ctx->code->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 b597389..bea2415 100644
--- a/dlls/vbscript/vbscript.c
+++ b/dlls/vbscript/vbscript.c
@@ -93,11 +93,20 @@ 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->script_obj;
     function_t *func_iter, **new_funcs;
     dynamic_var_t *var, **new_vars;
     size_t cnt, i;
 
+    if (!obj)
+    {
+        /* A persistent script with a dangling context calls these,
+           for some reason, even though it won't be executed. */
+        IActiveScriptSite_OnEnterScript(ctx->site);
+        IActiveScriptSite_OnLeaveScript(ctx->site);
+        return S_OK;
+    }
+
     cnt = obj->global_vars_cnt + code->main_code.var_cnt;
     if (cnt > obj->global_vars_size)
     {
@@ -196,7 +205,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 +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->script_obj != ctx->script_obj) code->script_obj = NULL;
         }
         else
         {
@@ -248,6 +258,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 +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,11 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript
     if(FAILED(hres))
         return hres;
 
+    /* Fix the dangling pointers to the old script dispatch */
+    LIST_FOR_EACH_ENTRY(code, &This->ctx->code_list, vbscode_t, entry)
+        if(code->script_obj)
+            code->script_obj = This->ctx->script_obj;
+
     This->ctx->site = pass;
     IActiveScriptSite_AddRef(This->ctx->site);
 
@@ -658,6 +676,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);
@@ -680,6 +703,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);
 
@@ -691,7 +715,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..dd6d5bf 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 *script_obj;
 
     BSTR *bstr_pool;
     unsigned bstr_pool_size;
-- 
2.21.0




More information about the wine-devel mailing list