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@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;