From: Francis De Brabandere <francisdb@gmail.com> Track the probe IDispatch in named_item_t::dim_probe_disp so qualified runtime access keeps using the original named_item_t::disp. Also stop lookup_named_item from eagerly fetching when called with no required- flags filter, which avoided a redundant compile-time GetItemInfo. --- dlls/vbscript/tests/vbscript.c | 8 +-- dlls/vbscript/vbscript.c | 106 +++++++++++++++++---------------- dlls/vbscript/vbscript.h | 1 + 3 files changed, 61 insertions(+), 54 deletions(-) diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index 3aac33b52da..1dd39d39338 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -2717,8 +2717,8 @@ static void test_named_item_dim_first_use_no_double_fetch(void) CHECK_CALLED(OnEnterScript); CHECK_CALLED(GetIDsOfNames_visible); CHECK_CALLED(OnLeaveScript); - todo_wine ok(called_GetItemInfo_visible == 1, - "GetItemInfo_visible called %d times, expected 1\n", called_GetItemInfo_visible); + ok(called_GetItemInfo_visible == 1, + "GetItemInfo_visible called %d times, expected 1\n", called_GetItemInfo_visible); expect_GetItemInfo_visible = 0; called_GetItemInfo_visible = 0; @@ -2811,8 +2811,8 @@ static void test_named_item_dim_two_slot_rotating(void) hres = IActiveScriptParse_ParseScriptText(parse, L"rotatingItem.testCall\n", NULL, NULL, NULL, 0, 0, 0, NULL, NULL); ok(hres == S_OK, "ParseScriptText failed: %08lx\n", hres); CHECK_CALLED(OnEnterScript); - todo_wine ok(called_testCall_rotating_a, "expected testCall on the runtime-cached (first) dispatch\n"); - todo_wine ok(!called_testCall_rotating_b, "wine routed testCall to the dim-refetched dispatch\n"); + ok(called_testCall_rotating_a, "expected testCall on the runtime-cached (first) dispatch\n"); + ok(!called_testCall_rotating_b, "wine routed testCall to the dim-refetched dispatch\n"); expect_testCall_rotating_a = 0; called_testCall_rotating_a = 0; expect_testCall_rotating_b = 0; called_testCall_rotating_b = 0; CHECK_CALLED(OnLeaveScript); diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index a758caa9d40..41338ea96de 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -94,6 +94,7 @@ static inline BOOL is_started(VBScript *This) } static HRESULT retrieve_named_item_disp(IActiveScriptSite *site, named_item_t *item); +static HRESULT fetch_named_item_disp(IActiveScriptSite *site, const WCHAR *name, IDispatch **out); HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res, BOOL extern_caller) { @@ -140,57 +141,48 @@ HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res, BOOL obj->global_funcs_size = cnt; } - /* For visible named items, the first exec_global_code with top-level - declarations release-and-refetches the host dispatch, then probes - each declared name (Dim variables, Subs, Functions, Classes) via - GetIDsOfNames. Subsequent parses reuse the cache. Names are always - declared regardless of whether they exist on the host dispatch. - TODO: It is unclear why Windows refetches the host dispatch on the - first declaration when the result is not used to skip name - creation. Perhaps it is used for some side effect or diagnostic - purpose that we have not yet identified. */ + /* For visible named items, native VBScript fetches a dedicated host + IDispatch via GetItemInfo on the first top-level declaration parse + and probes each declared name (Dim variables, Subs, Functions, + Classes) via GetIDsOfNames on it. The probe IDispatch is independent + of the runtime cache (named_item->disp) so subsequent qualified + access keeps using the runtime cache. The probe results are never + used to skip name creation; declarations always succeed. */ if(code->named_item && !(code->named_item->flags & SCRIPTITEM_CODEONLY) && (code->main_code.var_cnt || code->funcs || code->classes)) { if(!code->named_item->dim_disp_probed) { - if(code->named_item->disp) { - IDispatch_Release(code->named_item->disp); - code->named_item->disp = NULL; - } - retrieve_named_item_disp(ctx->site, code->named_item); + fetch_named_item_disp(ctx->site, code->named_item->name, &code->named_item->dim_probe_disp); code->named_item->dim_disp_probed = TRUE; } - } - if(code->named_item && code->named_item->disp - && !(code->named_item->flags & SCRIPTITEM_CODEONLY)) - { - class_desc_t *class_iter; - - /* Probe top-level declared names (Dim vars, Subs/Functions, - Classes) on the host dispatch. */ - for (i = 0; i < code->main_code.var_cnt; i++) { - BSTR name = SysAllocString(code->main_code.vars[i].name); - if(name) { - DISPID id; - disp_get_id(code->named_item->disp, name, VBDISP_CALLGET, TRUE, &id); - SysFreeString(name); + if(code->named_item->dim_probe_disp) { + class_desc_t *class_iter; + IDispatch *probe = code->named_item->dim_probe_disp; + + for (i = 0; i < code->main_code.var_cnt; i++) { + BSTR name = SysAllocString(code->main_code.vars[i].name); + if(name) { + DISPID id; + disp_get_id(probe, name, VBDISP_CALLGET, TRUE, &id); + SysFreeString(name); + } } - } - for (func_iter = code->funcs; func_iter; func_iter = func_iter->next) { - BSTR name = SysAllocString(func_iter->name); - if(name) { - DISPID id; - disp_get_id(code->named_item->disp, name, VBDISP_CALLGET, TRUE, &id); - SysFreeString(name); + for (func_iter = code->funcs; func_iter; func_iter = func_iter->next) { + BSTR name = SysAllocString(func_iter->name); + if(name) { + DISPID id; + disp_get_id(probe, name, VBDISP_CALLGET, TRUE, &id); + SysFreeString(name); + } } - } - for (class_iter = code->classes; class_iter; class_iter = class_iter->next) { - BSTR name = SysAllocString(class_iter->name); - if(name) { - DISPID id; - disp_get_id(code->named_item->disp, name, VBDISP_CALLGET, TRUE, &id); - SysFreeString(name); + for (class_iter = code->classes; class_iter; class_iter = class_iter->next) { + BSTR name = SysAllocString(class_iter->name); + if(name) { + DISPID id; + disp_get_id(probe, name, VBDISP_CALLGET, TRUE, &id); + SysFreeString(name); + } } } } @@ -273,25 +265,32 @@ static void exec_queued_code(script_ctx_t *ctx) } } -static HRESULT retrieve_named_item_disp(IActiveScriptSite *site, named_item_t *item) +static HRESULT fetch_named_item_disp(IActiveScriptSite *site, const WCHAR *name, IDispatch **out) { IUnknown *unk; HRESULT hres; - hres = IActiveScriptSite_GetItemInfo(site, item->name, SCRIPTINFO_IUNKNOWN, &unk, NULL); + *out = NULL; + if(!site) + return E_UNEXPECTED; + + hres = IActiveScriptSite_GetItemInfo(site, name, SCRIPTINFO_IUNKNOWN, &unk, NULL); if(FAILED(hres)) { WARN("GetItemInfo failed: %08lx\n", hres); return hres; } - hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp); + hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)out); IUnknown_Release(unk); - if(FAILED(hres)) { + if(FAILED(hres)) WARN("object does not implement IDispatch\n"); - return hres; - } - return S_OK; + return hres; +} + +static HRESULT retrieve_named_item_disp(IActiveScriptSite *site, named_item_t *item) +{ + return fetch_named_item_disp(site, item->name, &item->disp); } named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flags) @@ -306,7 +305,7 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned f if(FAILED(hres)) return NULL; } - if(!item->disp && (flags || !(item->flags & SCRIPTITEM_CODEONLY))) { + if(!item->disp && flags) { hres = retrieve_named_item_disp(ctx->site, item); if(FAILED(hres)) continue; } @@ -365,6 +364,12 @@ static void release_script(script_ctx_t *ctx) IDispatch_Release(item->disp); item->disp = NULL; } + if(item->dim_probe_disp) + { + IDispatch_Release(item->dim_probe_disp); + item->dim_probe_disp = NULL; + } + item->dim_disp_probed = FALSE; release_named_item_script_obj(item); if(!(item->flags & SCRIPTITEM_ISPERSISTENT)) { @@ -924,6 +929,7 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr item->ref = 1; item->disp = disp; + item->dim_probe_disp = NULL; item->flags = dwFlags; item->script_obj = NULL; item->dim_disp_probed = FALSE; diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index b0a674cc67f..c8aa84d5562 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -160,6 +160,7 @@ typedef struct { typedef struct named_item_t { ScriptDisp *script_obj; IDispatch *disp; + IDispatch *dim_probe_disp; unsigned ref; DWORD flags; LPWSTR name; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10393