Commit ba8429e7 authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

vbscript: Implement separate script dispatch objects for each named item.

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: 's avatarGabriel Ivăncescu <gabrielopcode@gmail.com> Signed-off-by: 's avatarJacek Caban <jacek@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 1546aff9
......@@ -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)
release_named_item(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)) {
......
......@@ -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
......
......@@ -97,6 +97,15 @@ 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;
HRESULT hres;
if(code->named_item) {
if(!code->named_item->script_obj) {
hres = create_script_disp(ctx, &code->named_item->script_obj);
if(FAILED(hres)) return hres;
}
obj = code->named_item->script_obj;
}
cnt = obj->global_vars_cnt + code->main_code.var_cnt;
if (cnt > obj->global_vars_size)
......@@ -196,6 +205,10 @@ 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->script_obj) {
hres = create_script_disp(ctx, &item->script_obj);
if(FAILED(hres)) return NULL;
}
if(!item->disp && (flags || !(item->flags & SCRIPTITEM_CODEONLY))) {
IUnknown *unk;
......@@ -221,6 +234,23 @@ 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;
}
void release_named_item(named_item_t *item)
{
if(--item->ref) return;
heap_free(item->name);
heap_free(item);
}
static void release_script(script_ctx_t *ctx)
{
vbscode_t *code, *code_next;
......@@ -234,6 +264,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 +279,8 @@ static void release_script(script_ctx_t *ctx)
list_remove(&iter->entry);
if(iter->disp)
IDispatch_Release(iter->disp);
heap_free(iter->name);
heap_free(iter);
release_named_item_script_obj(iter);
release_named_item(iter);
}
if(ctx->host_global) {
......@@ -658,8 +689,10 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr
return E_OUTOFMEMORY;
}
item->ref = 1;
item->disp = disp;
item->flags = dwFlags;
item->script_obj = NULL;
item->name = heap_strdupW(pstrName);
if(!item->name) {
if(disp)
......@@ -683,6 +716,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 +728,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;
}
......
......@@ -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;
......@@ -373,6 +376,7 @@ HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,D
HRESULT exec_script(script_ctx_t*,BOOL,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN;
void release_dynamic_var(dynamic_var_t*) DECLSPEC_HIDDEN;
named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN;
void release_named_item(named_item_t*) DECLSPEC_HIDDEN;
void clear_ei(EXCEPINFO*) DECLSPEC_HIDDEN;
HRESULT report_script_error(script_ctx_t*,const vbscode_t*,unsigned) DECLSPEC_HIDDEN;
void detach_global_objects(script_ctx_t*) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment