Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/compile.c | 17 +++++++---------- dlls/vbscript/vbscript.h | 1 + 2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index de45961..3eb3833 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -63,8 +63,6 @@ typedef struct { function_t *func; function_t *funcs; function_decl_t *func_decls; - - class_desc_t *classes; } compile_ctx_t;
static HRESULT compile_expression(compile_ctx_t*,expression_t*); @@ -1586,7 +1584,7 @@ static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name) { class_desc_t *iter;
- for(iter = ctx->classes; iter; iter = iter->next) { + for(iter = ctx->code->classes; iter; iter = iter->next) { if(!wcsicmp(iter->name, name)) return TRUE; } @@ -1754,8 +1752,8 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) } }
- class_desc->next = ctx->classes; - ctx->classes = class_desc; + class_desc->next = ctx->code->classes; + ctx->code->classes = class_desc; return S_OK; }
@@ -1795,7 +1793,7 @@ static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script) } }
- for(class = ctx->classes; class; class = class->next) { + for(class = ctx->code->classes; class; class = class->next) { if(lookup_script_identifier(script, class->name)) { FIXME("%s: redefined\n", debugstr_w(class->name)); return E_FAIL; @@ -1888,7 +1886,6 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
ctx.funcs = NULL; ctx.func_decls = NULL; - ctx.classes = NULL; ctx.labels = NULL; ctx.global_consts = NULL; ctx.stat_ctx = NULL; @@ -1985,8 +1982,8 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli script->global_funcs[script->global_funcs_cnt++] = func_iter; }
- if(ctx.classes) { - class_desc_t *class = ctx.classes; + if(ctx.code->classes) { + class_desc_t *class = ctx.code->classes;
while(1) { class->ctx = script; @@ -1996,7 +1993,7 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli }
class->next = script->classes; - script->classes = ctx.classes; + script->classes = ctx.code->classes; code->last_class = class; }
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index ef5cee2..29d790b 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -350,6 +350,7 @@ struct _vbscode_t { unsigned bstr_cnt; heap_pool_t heap;
+ class_desc_t *classes; class_desc_t *last_class;
struct list entry;
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/compile.c | 12 +++++------- dlls/vbscript/vbscript.h | 1 + 2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 3eb3833..50c9dfb 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -61,7 +61,6 @@ typedef struct { const_decl_t *global_consts;
function_t *func; - function_t *funcs; function_decl_t *func_decls; } compile_ctx_t;
@@ -1517,7 +1516,7 @@ static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name) { function_t *iter;
- for(iter = ctx->funcs; iter; iter = iter->next) { + for(iter = ctx->code->funcs; iter; iter = iter->next) { if(!wcsicmp(iter->name, name)) return TRUE; } @@ -1884,7 +1883,6 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli if(!ctx.code) return compile_error(script, E_OUTOFMEMORY);
- ctx.funcs = NULL; ctx.func_decls = NULL; ctx.labels = NULL; ctx.global_consts = NULL; @@ -1906,8 +1904,8 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli return compile_error(script, hres); }
- new_func->next = ctx.funcs; - ctx.funcs = new_func; + new_func->next = ctx.code->funcs; + ctx.code->funcs = new_func; }
for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) { @@ -1938,7 +1936,7 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli }
cnt = script->global_funcs_cnt; - for(func_iter = ctx.funcs; func_iter; func_iter = func_iter->next) + for(func_iter = ctx.code->funcs; func_iter; func_iter = func_iter->next) cnt++; if(cnt > script->global_funcs_size) { function_t **new_funcs; @@ -1969,7 +1967,7 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
script->global_vars_cnt += ctx.code->main_code.var_cnt;
- for(func_iter = ctx.funcs; func_iter; func_iter = func_iter->next) { + for(func_iter = ctx.code->funcs; func_iter; func_iter = func_iter->next) { unsigned i; for(i = 0; i < script->global_funcs_cnt; i++) { if(!wcsicmp(script->global_funcs[i]->name, func_iter->name)) { diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 29d790b..a59f341 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -350,6 +350,7 @@ struct _vbscode_t { unsigned bstr_cnt; heap_pool_t heap;
+ function_t *funcs; class_desc_t *classes; class_desc_t *last_class;
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/compile.c | 102 ++++++++++----------------------------- dlls/vbscript/vbscript.c | 79 ++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 76 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 50c9dfb..bc00209 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -1759,6 +1759,7 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier) { class_desc_t *class; + vbscode_t *code; unsigned i;
for(i = 0; i < script->global_vars_cnt; i++) { @@ -1776,6 +1777,30 @@ static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifi return TRUE; }
+ LIST_FOR_EACH_ENTRY(code, &script->code_list, vbscode_t, entry) { + unsigned var_cnt = code->main_code.var_cnt; + var_desc_t *vars = code->main_code.vars; + function_t *func; + + if(!code->pending_exec) + continue; + + for(i = 0; i < var_cnt; i++) { + if(!wcsicmp(vars[i].name, identifier)) + return TRUE; + } + + for(func = code->funcs; func; func = func->next) { + if(!wcsicmp(func->name, identifier)) + return TRUE; + } + + for(class = code->classes; class; class = class->next) { + if(!wcsicmp(class->name, identifier)) + return TRUE; + } + } + return FALSE; }
@@ -1864,13 +1889,11 @@ static void release_compiler(compile_ctx_t *ctx)
HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, DWORD flags, vbscode_t **ret) { - function_t *new_func, *func_iter; function_decl_t *func_decl; class_decl_t *class_decl; + function_t *new_func; compile_ctx_t ctx; vbscode_t *code; - size_t cnt; - unsigned i; HRESULT hres;
if (!src) src = L""; @@ -1922,79 +1945,6 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli return compile_error(script, hres); }
- cnt = script->global_vars_cnt + ctx.code->main_code.var_cnt; - if(cnt > script->global_vars_size) { - dynamic_var_t **new_vars; - if(script->global_vars) - new_vars = heap_realloc(script->global_vars, cnt * sizeof(*new_vars)); - else - new_vars = heap_alloc(cnt * sizeof(*new_vars)); - if(!new_vars) - return compile_error(script, E_OUTOFMEMORY); - script->global_vars = new_vars; - script->global_vars_size = cnt; - } - - cnt = script->global_funcs_cnt; - for(func_iter = ctx.code->funcs; func_iter; func_iter = func_iter->next) - cnt++; - if(cnt > script->global_funcs_size) { - function_t **new_funcs; - if(script->global_funcs) - new_funcs = heap_realloc(script->global_funcs, cnt * sizeof(*new_funcs)); - else - new_funcs = heap_alloc(cnt * sizeof(*new_funcs)); - if(!new_funcs) - return compile_error(script, E_OUTOFMEMORY); - script->global_funcs = new_funcs; - script->global_funcs_size = cnt; - } - - for(i = 0; i < ctx.code->main_code.var_cnt; i++) { - dynamic_var_t *var = compiler_alloc(ctx.code, sizeof(*var)); - if(!var) { - release_compiler(&ctx); - return compile_error(script, E_OUTOFMEMORY); - } - - var->name = ctx.code->main_code.vars[i].name; - V_VT(&var->v) = VT_EMPTY; - var->is_const = FALSE; - var->array = NULL; - - script->global_vars[script->global_vars_cnt + i] = var; - } - - script->global_vars_cnt += ctx.code->main_code.var_cnt; - - for(func_iter = ctx.code->funcs; func_iter; func_iter = func_iter->next) { - unsigned i; - for(i = 0; i < script->global_funcs_cnt; i++) { - if(!wcsicmp(script->global_funcs[i]->name, func_iter->name)) { - /* global function already exists, replace it */ - script->global_funcs[i] = func_iter; - break; - } - } - if(i == script->global_funcs_cnt) - script->global_funcs[script->global_funcs_cnt++] = func_iter; - } - - if(ctx.code->classes) { - class_desc_t *class = ctx.code->classes; - - while(1) { - class->ctx = script; - if(!class->next) - break; - class = class->next; - } - - class->next = script->classes; - script->classes = ctx.code->classes; - code->last_class = class; - } - code->is_persistent = (flags & SCRIPTTEXT_ISPERSISTENT) != 0;
if(TRACE_ON(vbscript_disas)) diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 07763fa..85107e7 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -82,6 +82,85 @@ static inline BOOL is_started(VBScript *This)
static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res) { + function_t *func_iter, **new_funcs; + dynamic_var_t *var, **new_vars; + size_t cnt, i; + + cnt = ctx->global_vars_cnt + code->main_code.var_cnt; + if (cnt > ctx->global_vars_size) + { + if (ctx->global_vars) + new_vars = heap_realloc(ctx->global_vars, cnt * sizeof(*new_vars)); + else + new_vars = heap_alloc(cnt * sizeof(*new_vars)); + if (!new_vars) + return E_OUTOFMEMORY; + ctx->global_vars = new_vars; + ctx->global_vars_size = cnt; + } + + cnt = ctx->global_funcs_cnt; + for (func_iter = code->funcs; func_iter; func_iter = func_iter->next) + cnt++; + if (cnt > ctx->global_funcs_size) + { + if (ctx->global_funcs) + new_funcs = heap_realloc(ctx->global_funcs, cnt * sizeof(*new_funcs)); + else + new_funcs = heap_alloc(cnt * sizeof(*new_funcs)); + if (!new_funcs) + return E_OUTOFMEMORY; + ctx->global_funcs = new_funcs; + ctx->global_funcs_size = cnt; + } + + for (i = 0; i < code->main_code.var_cnt; i++) + { + if (!(var = heap_pool_alloc(&ctx->heap, sizeof(*var)))) + return E_OUTOFMEMORY; + + var->name = code->main_code.vars[i].name; + V_VT(&var->v) = VT_EMPTY; + var->is_const = FALSE; + var->array = NULL; + + ctx->global_vars[ctx->global_vars_cnt + i] = var; + } + + ctx->global_vars_cnt += code->main_code.var_cnt; + + for (func_iter = code->funcs; func_iter; func_iter = func_iter->next) + { + for (i = 0; i < ctx->global_funcs_cnt; i++) + { + if (!wcsicmp(ctx->global_funcs[i]->name, func_iter->name)) + { + /* global function already exists, replace it */ + ctx->global_funcs[i] = func_iter; + break; + } + } + if (i == ctx->global_funcs_cnt) + ctx->global_funcs[ctx->global_funcs_cnt++] = func_iter; + } + + if (code->classes) + { + class_desc_t *class = code->classes; + + while (1) + { + class->ctx = ctx; + if (!class->next) + break; + class = class->next; + } + + class->next = ctx->classes; + ctx->classes = code->classes; + code->last_class = class; + } + code->pending_exec = FALSE; return exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res); }
Signed-off-by: Jacek Caban jacek@codeweavers.com
We need to free them while iterating an array as well as a linked list.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/interp.c | 16 ++++++++-------- dlls/vbscript/vbscript.c | 2 +- dlls/vbscript/vbscript.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index cf21601..d15a1b5 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -2243,22 +2243,22 @@ OP_LIST #undef X };
-void release_dynamic_vars(dynamic_var_t *var) +void release_dynamic_var(dynamic_var_t *var) { - while(var) { - VariantClear(&var->v); - if(var->array) - SafeArrayDestroy(var->array); - var = var->next; - } + VariantClear(&var->v); + if(var->array) + SafeArrayDestroy(var->array); }
static void release_exec(exec_ctx_t *ctx) { + dynamic_var_t *var; unsigned i;
VariantClear(&ctx->ret_val); - release_dynamic_vars(ctx->dynamic_vars); + + for(var = ctx->dynamic_vars; var; var = var->next) + release_dynamic_var(var);
if(ctx->vbthis) IDispatchEx_Release(&ctx->vbthis->IDispatchEx_iface); diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 85107e7..fdade9f 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -217,7 +217,7 @@ static void release_script(script_ctx_t *ctx) clear_ei(&ctx->ei);
for(i = 0; i < ctx->global_vars_cnt; i++) - VariantClear(&ctx->global_vars[i]->v); + release_dynamic_var(ctx->global_vars[i]);
heap_free(ctx->global_vars); heap_free(ctx->global_funcs); diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index a59f341..1cc36fd 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -361,7 +361,7 @@ void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN; HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD,vbscode_t**) DECLSPEC_HIDDEN; HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD,class_desc_t**) DECLSPEC_HIDDEN; HRESULT exec_script(script_ctx_t*,BOOL,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN; -void release_dynamic_vars(dynamic_var_t*) DECLSPEC_HIDDEN; +void release_dynamic_var(dynamic_var_t*) DECLSPEC_HIDDEN; IDispatch *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN; void clear_ei(EXCEPINFO*) DECLSPEC_HIDDEN; HRESULT report_script_error(script_ctx_t*) DECLSPEC_HIDDEN;
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Note that we have to move the non-persistent vbscode from the context's list, so it can be freed by the dispatch object only when it is released.
This will be needed for the TypeInfo and named contexts.
dlls/vbscript/compile.c | 15 ++++---- dlls/vbscript/interp.c | 39 +++++++++++---------- dlls/vbscript/vbdisp.c | 38 +++++++++++++++----- dlls/vbscript/vbscript.c | 75 +++++++++++++++------------------------- dlls/vbscript/vbscript.h | 43 ++++++++++++----------- 5 files changed, 107 insertions(+), 103 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index bc00209..9ddfacf 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -1758,21 +1758,22 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier) { + ScriptDisp *obj = script->script_obj; class_desc_t *class; vbscode_t *code; unsigned i;
- for(i = 0; i < script->global_vars_cnt; i++) { - if(!wcsicmp(script->global_vars[i]->name, identifier)) + for(i = 0; i < obj->global_vars_cnt; i++) { + if(!wcsicmp(obj->global_vars[i]->name, identifier)) return TRUE; }
- for(i = 0; i < script->global_funcs_cnt; i++) { - if(!wcsicmp(script->global_funcs[i]->name, identifier)) + for(i = 0; i < obj->global_funcs_cnt; i++) { + if(!wcsicmp(obj->global_funcs[i]->name, identifier)) return TRUE; }
- for(class = script->classes; class; class = class->next) { + for(class = obj->classes; class; class = class->next) { if(!wcsicmp(class->name, identifier)) return TRUE; } @@ -1977,8 +1978,8 @@ HRESULT compile_procedure(script_ctx_t *script, const WCHAR *src, const WCHAR *d desc->func_cnt = 1; desc->funcs->entries[VBDISP_CALLGET] = &code->main_code;
- desc->next = script->procs; - script->procs = desc; + desc->next = script->script_obj->procs; + script->script_obj->procs = desc;
*ret = desc; return S_OK; diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index d15a1b5..66ad206 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -94,7 +94,7 @@ static BOOL lookup_dynamic_vars(dynamic_var_t *var, const WCHAR *name, ref_t *re return FALSE; }
-static BOOL lookup_global_vars(script_ctx_t *script, const WCHAR *name, ref_t *ref) +static BOOL lookup_global_vars(ScriptDisp *script, const WCHAR *name, ref_t *ref) { dynamic_var_t **vars = script->global_vars; size_t i, cnt = script->global_vars_cnt; @@ -112,6 +112,7 @@ static BOOL lookup_global_vars(script_ctx_t *script, const WCHAR *name, ref_t *r
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; named_item_t *item; IDispatch *disp; unsigned i; @@ -175,11 +176,11 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_ } }
- if(lookup_global_vars(ctx->script, name, ref)) + if(lookup_global_vars(script_obj, name, ref)) return S_OK;
- for(i = 0; i < ctx->script->global_funcs_cnt; i++) { - function_t *func = ctx->script->global_funcs[i]; + for(i = 0; i < script_obj->global_funcs_cnt; i++) { + function_t *func = script_obj->global_funcs[i]; if(!wcsicmp(func->name, name)) { ref->type = REF_FUNC; ref->u.f = func; @@ -221,12 +222,13 @@ 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; dynamic_var_t *new_var; heap_pool_t *heap; WCHAR *str; unsigned size;
- heap = ctx->func->type == FUNC_GLOBAL ? &ctx->script->heap : &ctx->heap; + heap = ctx->func->type == FUNC_GLOBAL ? &script_obj->heap : &ctx->heap;
new_var = heap_pool_alloc(heap, sizeof(*new_var)); if(!new_var) @@ -243,19 +245,19 @@ static HRESULT add_dynamic_var(exec_ctx_t *ctx, const WCHAR *name, V_VT(&new_var->v) = VT_EMPTY;
if(ctx->func->type == FUNC_GLOBAL) { - size_t cnt = ctx->script->global_vars_cnt + 1; - if(cnt > ctx->script->global_vars_size) { + size_t cnt = script_obj->global_vars_cnt + 1; + if(cnt > script_obj->global_vars_size) { dynamic_var_t **new_vars; - if(ctx->script->global_vars) - new_vars = heap_realloc(ctx->script->global_vars, cnt * 2 * sizeof(*new_vars)); + if(script_obj->global_vars) + new_vars = heap_realloc(script_obj->global_vars, cnt * 2 * sizeof(*new_vars)); else new_vars = heap_alloc(cnt * 2 * sizeof(*new_vars)); if(!new_vars) return E_OUTOFMEMORY; - ctx->script->global_vars = new_vars; - ctx->script->global_vars_size = cnt * 2; + script_obj->global_vars = new_vars; + script_obj->global_vars_size = cnt * 2; } - ctx->script->global_vars[ctx->script->global_vars_cnt++] = new_var; + script_obj->global_vars[script_obj->global_vars_cnt++] = new_var; }else { new_var->next = ctx->dynamic_vars; ctx->dynamic_vars = new_var; @@ -1113,7 +1115,7 @@ static HRESULT interp_new(exec_ctx_t *ctx) return stack_push(ctx, &v); }
- for(class_desc = ctx->script->classes; class_desc; class_desc = class_desc->next) { + for(class_desc = ctx->script->script_obj->classes; class_desc; class_desc = class_desc->next) { if(!wcsicmp(class_desc->name, arg)) break; } @@ -1133,6 +1135,7 @@ static HRESULT interp_new(exec_ctx_t *ctx)
static HRESULT interp_dim(exec_ctx_t *ctx) { + ScriptDisp *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; @@ -1146,13 +1149,13 @@ static HRESULT interp_dim(exec_ctx_t *ctx)
if(ctx->func->type == FUNC_GLOBAL) { unsigned i; - for(i = 0; i < ctx->script->global_vars_cnt; i++) { - if(!wcsicmp(ctx->script->global_vars[i]->name, ident)) + for(i = 0; i < script_obj->global_vars_cnt; i++) { + if(!wcsicmp(script_obj->global_vars[i]->name, ident)) break; } - assert(i < ctx->script->global_vars_cnt); - v = &ctx->script->global_vars[i]->v; - array_ref = &ctx->script->global_vars[i]->array; + assert(i < script_obj->global_vars_cnt); + v = &script_obj->global_vars[i]->v; + array_ref = &script_obj->global_vars[i]->array; }else { ref_t ref;
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 12626e0..8bb2b68 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -569,11 +569,29 @@ static ULONG WINAPI ScriptDisp_Release(IDispatchEx *iface) { ScriptDisp *This = ScriptDisp_from_IDispatchEx(iface); LONG ref = InterlockedDecrement(&This->ref); + unsigned i;
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) { assert(!This->ctx); + + while (This->procs) + { + class_desc_t *class_desc = This->procs; + This->procs = class_desc->next; + heap_free(class_desc); + } + + for (i = 0; i < This->global_vars_cnt; i++) + release_dynamic_var(This->global_vars[i]); + + while (!list_empty(&This->code_list)) + release_vbscode(LIST_ENTRY(list_head(&This->code_list), vbscode_t, entry)); + + heap_pool_free(&This->heap); + heap_free(This->global_vars); + heap_free(This->global_funcs); heap_free(This); }
@@ -639,15 +657,15 @@ static HRESULT WINAPI ScriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DW if(!This->ctx) return E_UNEXPECTED;
- for(i = 0; i < This->ctx->global_vars_cnt; i++) { - if(!wcsicmp(This->ctx->global_vars[i]->name, bstrName)) { + for(i = 0; i < This->global_vars_cnt; i++) { + if(!wcsicmp(This->global_vars[i]->name, bstrName)) { *pid = i + 1; return S_OK; } }
- for(i = 0; i < This->ctx->global_funcs_cnt; i++) { - if(!wcsicmp(This->ctx->global_funcs[i]->name, bstrName)) { + for(i = 0; i < This->global_funcs_cnt; i++) { + if(!wcsicmp(This->global_funcs[i]->name, bstrName)) { *pid = i + 1 + DISPID_FUNCTION_MASK; return S_OK; } @@ -668,14 +686,14 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if (id & DISPID_FUNCTION_MASK) { id &= ~DISPID_FUNCTION_MASK; - if (id > This->ctx->global_funcs_cnt) + if (id > This->global_funcs_cnt) return DISP_E_MEMBERNOTFOUND;
switch (wFlags) { case DISPATCH_METHOD: case DISPATCH_METHOD | DISPATCH_PROPERTYGET: - hres = exec_script(This->ctx, TRUE, This->ctx->global_funcs[id - 1], NULL, pdp, pvarRes); + hres = exec_script(This->ctx, TRUE, This->global_funcs[id - 1], NULL, pdp, pvarRes); break; default: FIXME("Unsupported flags %x\n", wFlags); @@ -685,16 +703,16 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc return hres; }
- if (id > This->ctx->global_vars_cnt) + if (id > This->global_vars_cnt) return DISP_E_MEMBERNOTFOUND;
- if (This->ctx->global_vars[id - 1]->is_const) + if (This->global_vars[id - 1]->is_const) { FIXME("const not supported\n"); return E_NOTIMPL; }
- return invoke_variant_prop(This->ctx, &This->ctx->global_vars[id - 1]->v, wFlags, pdp, pvarRes); + return invoke_variant_prop(This->ctx, &This->global_vars[id - 1]->v, wFlags, pdp, pvarRes); }
static HRESULT WINAPI ScriptDisp_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) @@ -768,6 +786,8 @@ HRESULT create_script_disp(script_ctx_t *ctx, ScriptDisp **ret) script_disp->IDispatchEx_iface.lpVtbl = &ScriptDispVtbl; script_disp->ref = 1; script_disp->ctx = ctx; + heap_pool_init(&script_disp->heap); + list_init(&script_disp->code_list);
*ret = script_disp; return S_OK; diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index fdade9f..9d20433 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -82,41 +82,42 @@ 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; function_t *func_iter, **new_funcs; dynamic_var_t *var, **new_vars; size_t cnt, i;
- cnt = ctx->global_vars_cnt + code->main_code.var_cnt; - if (cnt > ctx->global_vars_size) + cnt = obj->global_vars_cnt + code->main_code.var_cnt; + if (cnt > obj->global_vars_size) { - if (ctx->global_vars) - new_vars = heap_realloc(ctx->global_vars, cnt * sizeof(*new_vars)); + if (obj->global_vars) + new_vars = heap_realloc(obj->global_vars, cnt * sizeof(*new_vars)); else new_vars = heap_alloc(cnt * sizeof(*new_vars)); if (!new_vars) return E_OUTOFMEMORY; - ctx->global_vars = new_vars; - ctx->global_vars_size = cnt; + obj->global_vars = new_vars; + obj->global_vars_size = cnt; }
- cnt = ctx->global_funcs_cnt; + cnt = obj->global_funcs_cnt; for (func_iter = code->funcs; func_iter; func_iter = func_iter->next) cnt++; - if (cnt > ctx->global_funcs_size) + if (cnt > obj->global_funcs_size) { - if (ctx->global_funcs) - new_funcs = heap_realloc(ctx->global_funcs, cnt * sizeof(*new_funcs)); + if (obj->global_funcs) + new_funcs = heap_realloc(obj->global_funcs, cnt * sizeof(*new_funcs)); else new_funcs = heap_alloc(cnt * sizeof(*new_funcs)); if (!new_funcs) return E_OUTOFMEMORY; - ctx->global_funcs = new_funcs; - ctx->global_funcs_size = cnt; + obj->global_funcs = new_funcs; + obj->global_funcs_size = cnt; }
for (i = 0; i < code->main_code.var_cnt; i++) { - if (!(var = heap_pool_alloc(&ctx->heap, sizeof(*var)))) + if (!(var = heap_pool_alloc(&obj->heap, sizeof(*var)))) return E_OUTOFMEMORY;
var->name = code->main_code.vars[i].name; @@ -124,24 +125,24 @@ static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res var->is_const = FALSE; var->array = NULL;
- ctx->global_vars[ctx->global_vars_cnt + i] = var; + obj->global_vars[obj->global_vars_cnt + i] = var; }
- ctx->global_vars_cnt += code->main_code.var_cnt; + obj->global_vars_cnt += code->main_code.var_cnt;
for (func_iter = code->funcs; func_iter; func_iter = func_iter->next) { - for (i = 0; i < ctx->global_funcs_cnt; i++) + for (i = 0; i < obj->global_funcs_cnt; i++) { - if (!wcsicmp(ctx->global_funcs[i]->name, func_iter->name)) + if (!wcsicmp(obj->global_funcs[i]->name, func_iter->name)) { /* global function already exists, replace it */ - ctx->global_funcs[i] = func_iter; + obj->global_funcs[i] = func_iter; break; } } - if (i == ctx->global_funcs_cnt) - ctx->global_funcs[ctx->global_funcs_cnt++] = func_iter; + if (i == obj->global_funcs_cnt) + obj->global_funcs[obj->global_funcs_cnt++] = func_iter; }
if (code->classes) @@ -156,8 +157,8 @@ static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res class = class->next; }
- class->next = ctx->classes; - ctx->classes = code->classes; + class->next = obj->classes; + obj->classes = code->classes; code->last_class = class; }
@@ -210,24 +211,10 @@ IDispatch *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flag static void release_script(script_ctx_t *ctx) { vbscode_t *code, *code_next; - class_desc_t *class_desc; - unsigned i;
collect_objects(ctx); clear_ei(&ctx->ei);
- for(i = 0; i < ctx->global_vars_cnt; i++) - release_dynamic_var(ctx->global_vars[i]); - - heap_free(ctx->global_vars); - heap_free(ctx->global_funcs); - ctx->global_vars = NULL; - ctx->global_vars_cnt = 0; - ctx->global_vars_size = 0; - ctx->global_funcs = NULL; - ctx->global_funcs_cnt = 0; - ctx->global_funcs_size = 0; - LIST_FOR_EACH_ENTRY_SAFE(code, code_next, &ctx->code_list, vbscode_t, entry) { if(code->is_persistent) @@ -236,7 +223,10 @@ static void release_script(script_ctx_t *ctx) if(code->last_class) code->last_class->next = NULL; } else - release_vbscode(code); + { + list_remove(&code->entry); + list_add_tail(&ctx->script_obj->code_list, &code->entry); + } }
while(!list_empty(&ctx->named_items)) { @@ -249,13 +239,6 @@ static void release_script(script_ctx_t *ctx) heap_free(iter); }
- while(ctx->procs) { - class_desc = ctx->procs; - ctx->procs = class_desc->next; - - heap_free(class_desc); - } - if(ctx->host_global) { IDispatch_Release(ctx->host_global); ctx->host_global = NULL; @@ -278,9 +261,6 @@ static void release_script(script_ctx_t *ctx) script_obj->ctx = NULL; IDispatchEx_Release(&script_obj->IDispatchEx_iface); } - - heap_pool_free(&ctx->heap); - heap_pool_init(&ctx->heap); }
static void release_code_list(script_ctx_t *ctx) @@ -1054,7 +1034,6 @@ HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pU }
ctx->safeopt = INTERFACE_USES_DISPEX; - heap_pool_init(&ctx->heap); list_init(&ctx->objects); list_init(&ctx->code_list); list_init(&ctx->named_items); diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 1cc36fd..58db0b5 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -120,11 +120,33 @@ struct _vbdisp_t { VARIANT props[1]; };
+typedef struct _dynamic_var_t { + struct _dynamic_var_t *next; + VARIANT v; + const WCHAR *name; + BOOL is_const; + SAFEARRAY *array; +} dynamic_var_t; + typedef struct { IDispatchEx IDispatchEx_iface; LONG ref;
+ dynamic_var_t **global_vars; + size_t global_vars_cnt; + size_t global_vars_size; + + function_t **global_funcs; + size_t global_funcs_cnt; + size_t global_funcs_size; + + class_desc_t *classes; + class_desc_t *procs; + script_ctx_t *ctx; + heap_pool_t heap; + + struct list code_list; } ScriptDisp;
typedef struct _builtin_prop_t builtin_prop_t; @@ -158,14 +180,6 @@ static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i) return dp->rgvarg + dp->cArgs-i-1; }
-typedef struct _dynamic_var_t { - struct _dynamic_var_t *next; - VARIANT v; - const WCHAR *name; - BOOL is_const; - SAFEARRAY *array; -} dynamic_var_t; - struct _script_ctx_t { IActiveScriptSite *site; LCID lcid; @@ -182,19 +196,6 @@ struct _script_ctx_t {
EXCEPINFO ei;
- dynamic_var_t **global_vars; - size_t global_vars_cnt; - size_t global_vars_size; - - function_t **global_funcs; - size_t global_funcs_cnt; - size_t global_funcs_size; - - class_desc_t *classes; - class_desc_t *procs; - - heap_pool_t heap; - struct list objects; struct list code_list; struct list named_items;
Hi Gabriel,
On 11/11/19 1:34 PM, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescugabrielopcode@gmail.com
Note that we have to move the non-persistent vbscode from the context's list, so it can be freed by the dispatch object only when it is released.
This will be needed for the TypeInfo and named contexts.
The patch looks good, assuming we're really going in the right direction. I would prefer to review it properly once I can see the code that needs it.
I signed off the rest of the series, because it didn't depend on this patch. The fact that no test failed without this patch gives you a nice hint about an interesting test...
Thanks,
Jacek
On 11/11/19 9:31 PM, Jacek Caban wrote:
Hi Gabriel,
On 11/11/19 1:34 PM, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescugabrielopcode@gmail.com
Note that we have to move the non-persistent vbscode from the context's list, so it can be freed by the dispatch object only when it is released.
This will be needed for the TypeInfo and named contexts.
The patch looks good, assuming we're really going in the right direction. I would prefer to review it properly once I can see the code that needs it.
I signed off the rest of the series, because it didn't depend on this patch. The fact that no test failed without this patch gives you a nice hint about an interesting test...
Thanks,
Jacek
Hi Jacek,
Yeah this patch doesn't influence existing tests, but it will be needed for TypeInfo and named contexts, where each named item will have its own separate script dispatch (and of course, in *those* tests, it will be required).
Thanks, Gabriel
On 11/12/19 1:36 PM, Gabriel Ivăncescu wrote:
On 11/11/19 9:31 PM, Jacek Caban wrote:
Hi Gabriel,
On 11/11/19 1:34 PM, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescugabrielopcode@gmail.com
Note that we have to move the non-persistent vbscode from the context's list, so it can be freed by the dispatch object only when it is released.
This will be needed for the TypeInfo and named contexts.
The patch looks good, assuming we're really going in the right direction. I would prefer to review it properly once I can see the code that needs it.
I signed off the rest of the series, because it didn't depend on this patch. The fact that no test failed without this patch gives you a nice hint about an interesting test...
Thanks,
Jacek
Hi Jacek,
Yeah this patch doesn't influence existing tests, but it will be needed for TypeInfo and named contexts, where each named item will have its own separate script dispatch (and of course, in *those* tests, it will be required).
Sure, just please send it together with TypeInfo changes so I can review it together.
Thanks,
Jacek
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/tests/vbscript.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index c0a582c..3fe73a9 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -53,27 +53,27 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
#define DEFINE_EXPECT(func) \ - static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + static int expect_ ## func = 0, called_ ## func = 0
#define SET_EXPECT(func) \ - expect_ ## func = TRUE + expect_ ## func = 1
#define CHECK_EXPECT2(func) \ do { \ ok(expect_ ##func, "unexpected call " #func "\n"); \ - called_ ## func = TRUE; \ + called_ ## func++; \ }while(0)
#define CHECK_EXPECT(func) \ do { \ CHECK_EXPECT2(func); \ - expect_ ## func = FALSE; \ + expect_ ## func--; \ }while(0)
#define CHECK_CALLED(func) \ do { \ ok(called_ ## func, "expected " #func "\n"); \ - expect_ ## func = called_ ## func = FALSE; \ + expect_ ## func = called_ ## func = 0; \ }while(0)
DEFINE_EXPECT(GetLCID);
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/tests/vbscript.c | 237 +++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+)
diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index 3fe73a9..b41d677 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -58,6 +58,9 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); #define SET_EXPECT(func) \ expect_ ## func = 1
+#define SET_EXPECT_MULTI(func, num) \ + expect_ ## func = num + #define CHECK_EXPECT2(func) \ do { \ ok(expect_ ##func, "unexpected call " #func "\n"); \ @@ -76,6 +79,12 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); expect_ ## func = called_ ## func = 0; \ }while(0)
+#define CHECK_CALLED_MULTI(func, num) \ + do { \ + ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \ + expect_ ## func = called_ ## func = 0; \ + }while(0) + DEFINE_EXPECT(GetLCID); DEFINE_EXPECT(OnStateChange_UNINITIALIZED); DEFINE_EXPECT(OnStateChange_STARTED); @@ -624,6 +633,233 @@ static void test_scriptdisp(void) ok(!ref, "ref = %d\n", ref); }
+static void test_code_persistence(void) +{ + IActiveScriptParse *parser; + IDispatchEx *script_disp; + IActiveScript *vbscript; + VARIANT var; + HRESULT hr; + DISPID id; + ULONG ref; + + vbscript = create_vbscript(); + + hr = IActiveScript_QueryInterface(vbscript, &IID_IActiveScriptParse, (void**)&parser); + ok(hr == S_OK, "Could not get IActiveScriptParse iface: %08x\n", hr); + test_state(vbscript, SCRIPTSTATE_UNINITIALIZED); + test_safety(vbscript); + + SET_EXPECT(GetLCID); + hr = IActiveScript_SetScriptSite(vbscript, &ActiveScriptSite); + ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr); + CHECK_CALLED(GetLCID); + + SET_EXPECT(OnStateChange_INITIALIZED); + hr = IActiveScriptParse_InitNew(parser); + ok(hr == S_OK, "InitNew failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_INITIALIZED); + test_state(vbscript, SCRIPTSTATE_INITIALIZED); + + hr = IActiveScriptParse_ParseScriptText(parser, L"" + "x = 1\n" + "dim y\ny = 2\n", + NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + + hr = IActiveScriptParse_ParseScriptText(parser, L"" + "dim z\n" + "y = 42\n" + "var = 10\n", + NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISPERSISTENT, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + + /* Pending code does not add identifiers to the global scope */ + script_disp = get_script_dispatch(vbscript); + id = 0; + get_disp_id(script_disp, "x", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + id = 0; + get_disp_id(script_disp, "y", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + id = 0; + get_disp_id(script_disp, "z", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + IDispatchEx_Release(script_disp); + + /* Uninitialized state removes code without SCRIPTTEXT_ISPERSISTENT */ + SET_EXPECT(OnStateChange_UNINITIALIZED); + hr = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_UNINITIALIZED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_UNINITIALIZED); + test_no_script_dispatch(vbscript); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hr = IActiveScript_SetScriptSite(vbscript, &ActiveScriptSite); + ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + hr = IActiveScriptParse_ParseScriptText(parser, L"var = 20\n", NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + + SET_EXPECT(OnStateChange_CONNECTED); + SET_EXPECT_MULTI(OnEnterScript, 2); + SET_EXPECT_MULTI(OnLeaveScript, 2); + hr = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_CONNECTED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_CONNECTED); + CHECK_CALLED_MULTI(OnEnterScript, 2); + CHECK_CALLED_MULTI(OnLeaveScript, 2); + test_state(vbscript, SCRIPTSTATE_CONNECTED); + + script_disp = get_script_dispatch(vbscript); + id = 0; + get_disp_id(script_disp, "x", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + id = 0; + get_disp_id(script_disp, "y", S_OK, &id); + ok(id != -1, "id = -1\n"); + id = 0; + get_disp_id(script_disp, "z", S_OK, &id); + ok(id != -1, "id = -1\n"); + IDispatchEx_Release(script_disp); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parser, L"y", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_I2 && V_I2(&var) == 42, "V_VT(y) = %d, V_I2(y) = %d\n", V_VT(&var), V_I2(&var)); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parser, L"var", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_I2 && V_I2(&var) == 20, "V_VT(var) = %d, V_I2(var) = %d\n", V_VT(&var), V_I2(&var)); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + /* Uninitialized state does not remove persistent code, even if it was executed */ + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_UNINITIALIZED); + hr = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_UNINITIALIZED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_UNINITIALIZED); + test_no_script_dispatch(vbscript); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hr = IActiveScript_SetScriptSite(vbscript, &ActiveScriptSite); + ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + script_disp = get_script_dispatch(vbscript); + id = 0; + get_disp_id(script_disp, "z", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + IDispatchEx_Release(script_disp); + + SET_EXPECT(OnStateChange_CONNECTED); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_CONNECTED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_CONNECTED); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + test_state(vbscript, SCRIPTSTATE_CONNECTED); + + script_disp = get_script_dispatch(vbscript); + id = 0; + get_disp_id(script_disp, "z", S_OK, &id); + ok(id != -1, "id = -1\n"); + IDispatchEx_Release(script_disp); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parser, L"y", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_I2 && V_I2(&var) == 42, "V_VT(y) = %d, V_I2(y) = %d\n", V_VT(&var), V_I2(&var)); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parser, L"var", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_I2 && V_I2(&var) == 10, "V_VT(var) = %d, V_I2(var) = %d\n", V_VT(&var), V_I2(&var)); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_UNINITIALIZED); + hr = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_UNINITIALIZED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_UNINITIALIZED); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hr = IActiveScript_SetScriptSite(vbscript, &ActiveScriptSite); + ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + hr = IActiveScriptParse_ParseScriptText(parser, L"dim y\ny = 2\n", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISPERSISTENT, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + + /* Closing the script engine removes all code (even if it's pending and persistent) */ + SET_EXPECT(OnStateChange_CLOSED); + hr = IActiveScript_Close(vbscript); + ok(hr == S_OK, "Close failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_CLOSED); + test_state(vbscript, SCRIPTSTATE_CLOSED); + test_no_script_dispatch(vbscript); + + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(GetLCID); + hr = IActiveScript_SetScriptSite(vbscript, &ActiveScriptSite); + ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(GetLCID); + test_state(vbscript, SCRIPTSTATE_INITIALIZED); + + SET_EXPECT(OnStateChange_CONNECTED); + hr = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_CONNECTED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_CONNECTED); + test_state(vbscript, SCRIPTSTATE_CONNECTED); + + script_disp = get_script_dispatch(vbscript); + id = 0; + get_disp_id(script_disp, "y", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + id = 0; + get_disp_id(script_disp, "z", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + IDispatchEx_Release(script_disp); + + IActiveScriptParse_Release(parser); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_CLOSED); + ref = IActiveScript_Release(vbscript); + ok(!ref, "ref = %d\n", ref); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_CLOSED); +} + static void test_vbscript(void) { IActiveScriptParseProcedure2 *parse_proc; @@ -1249,6 +1485,7 @@ START_TEST(vbscript) test_vbscript_initializing(); test_named_items(); test_scriptdisp(); + test_code_persistence(); test_RegExp(); test_RegExp_Replace(); }else {
Signed-off-by: Jacek Caban jacek@codeweavers.com