Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
We need to append them at the end for next patches to pass the tests. It will also be needed when implementing the SCRIPTITEM_ISPERSISTENT flag.
dlls/jscript/engine.c | 2 +- dlls/jscript/jscript.c | 26 +++++++++----------------- dlls/jscript/jscript.h | 4 ++-- 3 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 4e28b63..7da8f70 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -591,7 +591,7 @@ static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t DISPID id; HRESULT hres;
- for(item = ctx->named_items; item; item = item->next) { + LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) { if(item->flags & SCRIPTITEM_GLOBALMEMBERS) { hres = disp_get_id(ctx, item->disp, identifier, identifier, 0, &id); if(SUCCEEDED(hres)) { diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 5e9b153..b878aa5 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -113,7 +113,7 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *item_name, unsig named_item_t *item; HRESULT hr;
- for(item = ctx->named_items; item; item = item->next) { + LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) { if((item->flags & flags) == flags && !wcscmp(item->name, item_name)) { if(!item->disp && (flags || !(item->flags & SCRIPTITEM_CODEONLY))) { IUnknown *unk; @@ -414,20 +414,13 @@ static void decrease_state(JScript *This, SCRIPTSTATE state) This->ctx->host_global = NULL; }
- if(This->ctx->named_items) { - named_item_t *iter, *iter2; + while(!list_empty(&This->ctx->named_items)) { + named_item_t *iter = LIST_ENTRY(list_head(&This->ctx->named_items), named_item_t, entry);
- iter = This->ctx->named_items; - while(iter) { - iter2 = iter->next; - - if(iter->disp) - IDispatch_Release(iter->disp); - release_named_item(iter); - iter = iter2; - } - - This->ctx->named_items = NULL; + list_remove(&iter->entry); + if(iter->disp) + IDispatch_Release(iter->disp); + release_named_item(iter); }
if(This->ctx->secmgr) { @@ -681,6 +674,7 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface, ctx->version = This->version; ctx->html_mode = This->html_mode; ctx->acc = jsval_undefined(); + list_init(&ctx->named_items); heap_pool_init(&ctx->tmp_heap);
hres = create_jscaller(ctx); @@ -851,9 +845,7 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, return E_OUTOFMEMORY; }
- item->next = This->ctx->named_items; - This->ctx->named_items = item; - + list_add_tail(&This->ctx->named_items, &item->entry); return S_OK; }
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index efd5a54..7f34b55 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -210,7 +210,7 @@ typedef struct named_item_t { DWORD flags; LPWSTR name;
- struct named_item_t *next; + struct list entry; } named_item_t;
named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN; @@ -409,7 +409,7 @@ struct _script_ctx_t { IActiveScript *active_script;
struct _call_frame_t *call_ctx; - named_item_t *named_items; + struct list named_items; IActiveScriptSite *site; IInternetHostSecurityManager *secmgr; DWORD safeopt;
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/engine.c | 21 +++++++++++++++++---- dlls/jscript/engine.h | 1 + dlls/jscript/function.c | 4 +--- dlls/jscript/jscript.c | 10 ---------- dlls/jscript/jscript.h | 2 -- 5 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 7da8f70..9a87b9f 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -605,6 +605,21 @@ static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t return FALSE; }
+IDispatch *lookup_global_host(script_ctx_t *ctx) +{ + IDispatch *disp = NULL; + named_item_t *item; + + LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) { + if(!(item->flags & SCRIPTITEM_GLOBALMEMBERS)) continue; + disp = item->disp; + break; + } + if(!disp) disp = to_disp(ctx->global); + + return disp; +} + static int __cdecl local_ref_cmp(const void *key, const void *ref) { return wcscmp((const WCHAR*)key, ((const local_ref_t*)ref)->name); @@ -2700,7 +2715,7 @@ static void print_backtrace(script_ctx_t *ctx) WARN("%u\t", depth); depth++;
- if(frame->this_obj && frame->this_obj != to_disp(ctx->global) && frame->this_obj != ctx->host_global) + if(frame->this_obj && frame->this_obj != to_disp(ctx->global) && frame->this_obj != lookup_global_host(ctx)) WARN("%p->", frame->this_obj); WARN("%s(", frame->function->name ? debugstr_w(frame->function->name) : "[unnamed]"); if(frame->base_scope && frame->base_scope->frame) { @@ -3057,10 +3072,8 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi frame->stack_base = ctx->stack_top; if(this_obj) frame->this_obj = this_obj; - else if(ctx->host_global) - frame->this_obj = ctx->host_global; else - frame->this_obj = to_disp(ctx->global); + frame->this_obj = lookup_global_host(ctx); IDispatch_AddRef(frame->this_obj);
if(function_instance) diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index cad46e1..7be98c5 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -170,6 +170,7 @@ typedef struct _function_code_t { bytecode_t *bytecode; } function_code_t;
+IDispatch *lookup_global_host(script_ctx_t*) DECLSPEC_HIDDEN; local_ref_t *lookup_local(const function_code_t*,const WCHAR*) DECLSPEC_HIDDEN;
struct _bytecode_t { diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index baa5eb1..ef0de96 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -612,10 +612,8 @@ static HRESULT NativeFunction_call(script_ctx_t *ctx, FunctionInstance *func, ID
if(this_disp) set_disp(&vthis, this_disp); - else if(ctx->host_global) - set_disp(&vthis, ctx->host_global); else - set_jsdisp(&vthis, ctx->global); + set_disp(&vthis, lookup_global_host(ctx));
hres = function->proc(ctx, &vthis, flags & ~DISPATCH_JSCRIPT_INTERNAL_MASK, argc, argv, r);
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index b878aa5..36d9f84 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -409,11 +409,6 @@ static void decrease_state(JScript *This, SCRIPTSTATE state) case SCRIPTSTATE_INITIALIZED: clear_script_queue(This);
- if(This->ctx->host_global) { - IDispatch_Release(This->ctx->host_global); - This->ctx->host_global = NULL; - } - while(!list_empty(&This->ctx->named_items)) { named_item_t *iter = LIST_ENTRY(list_head(&This->ctx->named_items), named_item_t, entry);
@@ -820,11 +815,6 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, WARN("object does not implement IDispatch\n"); return hres; } - - if(This->ctx->host_global) - IDispatch_Release(This->ctx->host_global); - IDispatch_AddRef(disp); - This->ctx->host_global = disp; }
item = heap_alloc(sizeof(*item)); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 7f34b55..f9d6992 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -422,8 +422,6 @@ struct _script_ctx_t {
heap_pool_t tmp_heap;
- IDispatch *host_global; - jsval_t *stack; unsigned stack_size; unsigned stack_top;
Hi Gabriel,
On 02.03.2020 14:38, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescugabrielopcode@gmail.com
dlls/jscript/engine.c | 21 +++++++++++++++++---- dlls/jscript/engine.h | 1 + dlls/jscript/function.c | 4 +--- dlls/jscript/jscript.c | 10 ---------- dlls/jscript/jscript.h | 2 -- 5 files changed, 19 insertions(+), 19 deletions(-)
How about storing this as NULL for global code and then do the lookup in interp_this() when this_obj is NULL?
Thanks,
Jacek
Hi Jacek,
On 05/03/2020 17:37, Jacek Caban wrote:
Hi Gabriel,
On 02.03.2020 14:38, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescugabrielopcode@gmail.com
dlls/jscript/engine.c | 21 +++++++++++++++++---- dlls/jscript/engine.h | 1 + dlls/jscript/function.c | 4 +--- dlls/jscript/jscript.c | 10 ---------- dlls/jscript/jscript.h | 2 -- 5 files changed, 19 insertions(+), 19 deletions(-)
How about storing this as NULL for global code and then do the lookup in interp_this() when this_obj is NULL?
Thanks,
Jacek
It seems to be used in multiple places other than interp_this: interp_ret, pop_call_frame. And also for eval in global.c. Wouldn't that require to look it up in each of them every time?
I'm not sure if it's better since it adds more code, too. What do you think?
Thanks, Gabriel
On 05.03.2020 17:14, Gabriel Ivăncescu wrote:
Hi Jacek,
On 05/03/2020 17:37, Jacek Caban wrote:
Hi Gabriel,
On 02.03.2020 14:38, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescugabrielopcode@gmail.com
dlls/jscript/engine.c | 21 +++++++++++++++++---- dlls/jscript/engine.h | 1 + dlls/jscript/function.c | 4 +--- dlls/jscript/jscript.c | 10 ---------- dlls/jscript/jscript.h | 2 -- 5 files changed, 19 insertions(+), 19 deletions(-)
How about storing this as NULL for global code and then do the lookup in interp_this() when this_obj is NULL?
Thanks,
Jacek
It seems to be used in multiple places other than interp_this: interp_ret, pop_call_frame. And also for eval in global.c. Wouldn't that require to look it up in each of them every time?
It needs a review to be sure, but I think that JS this will never be NULL when a function is called as a constructor, so interp_ret is not a problem. pop_call_frame only releases the object, so it's not an issue. Once you change the meaning of NULL, you may use just use NULL in eval() for global code.
Jacek
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/jscript/compile.c | 2 ++ dlls/jscript/dispex.c | 1 + dlls/jscript/engine.c | 33 ++++++++++++++++-- dlls/jscript/engine.h | 2 ++ dlls/jscript/global.c | 9 ++++- dlls/jscript/jscript.c | 78 ++++++++++++++++++++++++++++++++++++++++-- dlls/jscript/jscript.h | 2 ++ 7 files changed, 121 insertions(+), 6 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 61db10c..07027c2 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -2250,6 +2250,8 @@ void release_bytecode(bytecode_t *code) for(i=0; i < code->str_cnt; i++) jsstr_release(code->str_pool[i]);
+ if(code->named_item) + release_named_item(code->named_item); heap_free(code->source); heap_pool_free(&code->heap); heap_free(code->bstr_pool); diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index e986de6..a0c8f38 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1527,6 +1527,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc }
enter_script(This->ctx, &ei); + ei.script_obj = This;
switch(wFlags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 9a87b9f..f7890c9 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -669,6 +669,15 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re return S_OK; } } + + if(ctx->call_ctx->bytecode->named_item) { + jsdisp_t *script_obj = ctx->call_ctx->bytecode->named_item->script_obj; + hres = jsdisp_get_id(script_obj, identifier, 0, &id); + if(SUCCEEDED(hres)) { + exprval_set_disp_ref(ret, to_disp(script_obj), id); + return S_OK; + } + } }
hres = jsdisp_get_id(ctx->global, identifier, 0, &id); @@ -1251,13 +1260,17 @@ static HRESULT interp_identifier_ref(script_ctx_t *ctx, BSTR identifier, unsigne return hres;
if(exprval.type == EXPRVAL_INVALID && (flags & fdexNameEnsure)) { + jsdisp_t *script_obj = ctx->global; DISPID id;
- hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id); + if(ctx->call_ctx->bytecode->named_item) + script_obj = ctx->call_ctx->bytecode->named_item->script_obj; + + hres = jsdisp_get_id(script_obj, identifier, fdexNameEnsure, &id); if(FAILED(hres)) return hres;
- exprval_set_disp_ref(&exprval, to_disp(ctx->global), id); + exprval_set_disp_ref(&exprval, to_disp(script_obj), id); }
if(exprval.type == EXPRVAL_JSVAL || exprval.type == EXPRVAL_INVALID) { @@ -2987,6 +3000,15 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi unsigned i; HRESULT hres;
+ if(bytecode->named_item) { + if(!bytecode->named_item->script_obj) { + hres = create_named_item_script_obj(ctx, bytecode->named_item); + if(FAILED(hres)) return hres; + } + if(variable_obj == ctx->global) + variable_obj = bytecode->named_item->script_obj; + } + if(!ctx->ei->enter_notified) { ctx->ei->enter_notified = TRUE; IActiveScriptSite_OnEnterScript(ctx->site); @@ -3009,6 +3031,8 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi }
if(flags & (EXEC_GLOBAL | EXEC_EVAL)) { + BOOL lookup_globals = (flags & EXEC_GLOBAL) && !bytecode->named_item; + for(i=0; i < function->var_cnt; i++) { TRACE("[%d] %s %d\n", i, debugstr_w(function->variables[i].name), function->variables[i].func_id); if(function->variables[i].func_id != -1) { @@ -3020,7 +3044,7 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi
hres = jsdisp_propput_name(variable_obj, function->variables[i].name, jsval_obj(func_obj)); jsdisp_release(func_obj); - }else if(!(flags & EXEC_GLOBAL) || !lookup_global_members(ctx, function->variables[i].name, NULL)) { + }else if(!lookup_globals || !lookup_global_members(ctx, function->variables[i].name, NULL)) { DISPID id = 0;
hres = jsdisp_get_id(variable_obj, function->variables[i].name, fdexNameEnsure, &id); @@ -3072,6 +3096,9 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi frame->stack_base = ctx->stack_top; if(this_obj) frame->this_obj = this_obj; + else if(bytecode->named_item) + frame->this_obj = (bytecode->named_item->flags & SCRIPTITEM_CODEONLY) + ? to_disp(bytecode->named_item->script_obj) : bytecode->named_item->disp; else frame->this_obj = lookup_global_host(ctx); IDispatch_AddRef(frame->this_obj); diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 7be98c5..4a54ddf 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -181,6 +181,7 @@ struct _bytecode_t { heap_pool_t heap;
function_code_t global_code; + named_item_t *named_item;
WCHAR *source; UINT64 source_context; @@ -232,6 +233,7 @@ struct _jsexcept_t { jsstr_t *message; jsstr_t *line;
+ jsdisp_t *script_obj; bytecode_t *code; unsigned loc;
diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index e2758bf..bb53709 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -181,6 +181,7 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a { call_frame_t *frame = ctx->call_ctx; DWORD exec_flags = EXEC_EVAL; + jsdisp_t *context; bytecode_t *code; const WCHAR *src; HRESULT hres; @@ -210,12 +211,18 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a return hres; }
+ if(frame && frame->bytecode->named_item) { + code->named_item = frame->bytecode->named_item; + code->named_item->ref++; + } + context = frame ? frame->variable_obj : (ctx->ei->script_obj ? ctx->ei->script_obj : ctx->global); + if(!frame || (frame->flags & EXEC_GLOBAL)) exec_flags |= EXEC_GLOBAL; if(flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) exec_flags |= EXEC_RETURN_TO_INTERP; hres = exec_source(ctx, exec_flags, code, &code->global_code, frame ? frame->scope : NULL, - frame ? frame->this_obj : NULL, NULL, frame ? frame->variable_obj : ctx->global, 0, NULL, r); + frame ? frame->this_obj : NULL, NULL, context, 0, NULL, r); release_bytecode(code); return hres; } diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 36d9f84..535f95d 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -108,6 +108,27 @@ static inline BOOL is_started(script_ctx_t *ctx) || ctx->state == SCRIPTSTATE_DISCONNECTED; }
+HRESULT create_named_item_script_obj(script_ctx_t *ctx, named_item_t *item) +{ + static const builtin_info_t disp_info = { + JSCLASS_GLOBAL, + {NULL, NULL, 0}, + 0, NULL, + NULL, + NULL + }; + + return create_dispex(ctx, &disp_info, NULL, &item->script_obj); +} + +static void release_named_item_script_obj(named_item_t *item) +{ + if(!item->script_obj) return; + + jsdisp_release(item->script_obj); + item->script_obj = NULL; +} + named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *item_name, unsigned flags) { named_item_t *item; @@ -115,6 +136,10 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *item_name, unsig
LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) { if((item->flags & flags) == flags && !wcscmp(item->name, item_name)) { + if(!item->script_obj && !(item->flags & SCRIPTITEM_GLOBALMEMBERS)) { + hr = create_named_item_script_obj(ctx, item); + if(FAILED(hr)) return NULL; + } if(!item->disp && (flags || !(item->flags & SCRIPTITEM_CODEONLY))) { IUnknown *unk;
@@ -371,6 +396,15 @@ static void clear_persistent_code_list(JScript *This) } }
+static void release_persistent_script_objs(JScript *This) +{ + bytecode_t *iter; + + LIST_FOR_EACH_ENTRY(iter, &This->persistent_code, bytecode_t, entry) + if(iter->named_item) + release_named_item_script_obj(iter->named_item); +} + static void exec_queued_code(JScript *This) { bytecode_t *iter; @@ -408,6 +442,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state) /* FALLTHROUGH */ case SCRIPTSTATE_INITIALIZED: clear_script_queue(This); + release_persistent_script_objs(This);
while(!list_empty(&This->ctx->named_items)) { named_item_t *iter = LIST_ENTRY(list_head(&This->ctx->named_items), named_item_t, entry); @@ -415,6 +450,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state) list_remove(&iter->entry); if(iter->disp) IDispatch_Release(iter->disp); + release_named_item_script_obj(iter); release_named_item(iter); }
@@ -827,6 +863,7 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, item->ref = 1; item->disp = disp; item->flags = dwFlags; + item->script_obj = NULL; item->name = heap_strdupW(pstrName); if(!item->name) { if(disp) @@ -851,6 +888,7 @@ static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR IDispatch **ppdisp) { JScript *This = impl_from_IActiveScript(iface); + jsdisp_t *script_obj;
TRACE("(%p)->(%s %p)\n", This, debugstr_w(pstrItemName), ppdisp);
@@ -862,7 +900,14 @@ static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR return E_UNEXPECTED; }
- *ppdisp = to_disp(This->ctx->global); + script_obj = This->ctx->global; + if(pstrItemName) { + named_item_t *item = lookup_named_item(This->ctx, pstrItemName, 0); + if(!item) return E_INVALIDARG; + if(item->script_obj) script_obj = item->script_obj; + } + + *ppdisp = to_disp(script_obj); IDispatch_AddRef(*ppdisp); return S_OK; } @@ -983,6 +1028,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) { JScript *This = impl_from_IActiveScriptParse(iface); + named_item_t *item = NULL; bytecode_t *code; jsexcept_t ei; HRESULT hres; @@ -994,11 +1040,24 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED;
+ if(pstrItemName) { + item = lookup_named_item(This->ctx, pstrItemName, 0); + if(!item) { + WARN("Unknown context %s\n", debugstr_w(pstrItemName)); + return E_INVALIDARG; + } + if(!item->script_obj) item = NULL; + } + enter_script(This->ctx, &ei); hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLine, NULL, pstrDelimiter, (dwFlags & SCRIPTTEXT_ISEXPRESSION) != 0, This->is_encode, &code); if(FAILED(hres)) return leave_script(This->ctx, hres); + if(item) { + code->named_item = item; + item->ref++; + }
if(dwFlags & SCRIPTTEXT_ISEXPRESSION) { jsval_t r; @@ -1075,6 +1134,7 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp) { JScript *This = impl_from_IActiveScriptParseProcedure2(iface); + named_item_t *item = NULL; bytecode_t *code; jsdisp_t *dispex; jsexcept_t ei; @@ -1087,11 +1147,25 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED;
+ if(pstrItemName) { + item = lookup_named_item(This->ctx, pstrItemName, 0); + if(!item) { + WARN("Unknown context %s\n", debugstr_w(pstrItemName)); + return E_INVALIDARG; + } + if(!item->script_obj) item = NULL; + } + enter_script(This->ctx, &ei); hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLineNumber, pstrFormalParams, pstrDelimiter, FALSE, This->is_encode, &code); - if(SUCCEEDED(hres)) + if(SUCCEEDED(hres)) { + if(item) { + code->named_item = item; + item->ref++; + } hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex); + } release_bytecode(code); hres = leave_script(This->ctx, hres); if(FAILED(hres)) diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index f9d6992..804f95e 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -205,6 +205,7 @@ typedef HRESULT (*builtin_setter_t)(script_ctx_t*,jsdisp_t*,jsval_t); HRESULT builtin_set_const(script_ctx_t*,jsdisp_t*,jsval_t) DECLSPEC_HIDDEN;
typedef struct named_item_t { + jsdisp_t *script_obj; IDispatch *disp; unsigned ref; DWORD flags; @@ -213,6 +214,7 @@ typedef struct named_item_t { struct list entry; } named_item_t;
+HRESULT create_named_item_script_obj(script_ctx_t*,named_item_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;
Hi Gabriel,
On 02.03.2020 14:39, Gabriel Ivăncescu wrote:
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ăncescugabrielopcode@gmail.com
dlls/jscript/compile.c | 2 ++ dlls/jscript/dispex.c | 1 + dlls/jscript/engine.c | 33 ++++++++++++++++-- dlls/jscript/engine.h | 2 ++ dlls/jscript/global.c | 9 ++++- dlls/jscript/jscript.c | 78 ++++++++++++++++++++++++++++++++++++++++-- dlls/jscript/jscript.h | 2 ++ 7 files changed, 121 insertions(+), 6 deletions(-)
Please try to split it some more, it's not really reviewable in current form. I know it may be tricky to get it split without breaking anything, but I think it could be done. One way to do it would be to introduce script_obj inside named item struct, but set it to global script object. Using it would then behave just like current use of global object. You could then replace its usage one by one (which should make it a lot easier to review). Once all users are fixed, you may then change it to be a separated object in most cases.
Thanks,
Jacek
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/tests/jscript.c | 704 ++++++++++++++++++++++++++++++++++- 1 file changed, 691 insertions(+), 13 deletions(-)
diff --git a/dlls/jscript/tests/jscript.c b/dlls/jscript/tests/jscript.c index 84805b1..869c3b4 100644 --- a/dlls/jscript/tests/jscript.c +++ b/dlls/jscript/tests/jscript.c @@ -97,6 +97,13 @@ DEFINE_EXPECT(OnStateChange_CLOSED); DEFINE_EXPECT(OnStateChange_INITIALIZED); DEFINE_EXPECT(OnEnterScript); DEFINE_EXPECT(OnLeaveScript); +DEFINE_EXPECT(OnScriptError); +DEFINE_EXPECT(GetIDsOfNames); +DEFINE_EXPECT(GetItemInfo_global); +DEFINE_EXPECT(GetItemInfo_global_code); +DEFINE_EXPECT(GetItemInfo_visible); +DEFINE_EXPECT(GetItemInfo_visible_code); +DEFINE_EXPECT(testCall);
static const CLSID *engine_clsid = &CLSID_JScript;
@@ -111,6 +118,143 @@ static void _test_state(unsigned line, IActiveScript *script, SCRIPTSTATE exstat ok_(__FILE__,line) (state == exstate, "state=%d, expected %d\n", state, exstate); }
+static HRESULT WINAPI Dispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid)) { + *ppv = iface; + IDispatch_AddRef(iface); + return S_OK; + } + + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI Dispatch_AddRef(IDispatch *iface) +{ + return 2; +} + +static ULONG WINAPI Dispatch_Release(IDispatch *iface) +{ + return 1; +} + +static ULONG global_named_item_ref, visible_named_item_ref, visible_code_named_item_ref; + +static ULONG WINAPI global_AddRef(IDispatch *iface) +{ + return ++global_named_item_ref; +} + +static ULONG WINAPI global_Release(IDispatch *iface) +{ + return --global_named_item_ref; +} + +static ULONG WINAPI visible_AddRef(IDispatch *iface) +{ + return ++visible_named_item_ref; +} + +static ULONG WINAPI visible_Release(IDispatch *iface) +{ + return --visible_named_item_ref; +} + +static ULONG WINAPI visible_code_AddRef(IDispatch *iface) +{ + return ++visible_code_named_item_ref; +} + +static ULONG WINAPI visible_code_Release(IDispatch *iface) +{ + return --visible_code_named_item_ref; +} + +static HRESULT WINAPI Dispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Dispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) +{ + return DISP_E_BADINDEX; +} + +static HRESULT WINAPI Dispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *names, UINT name_cnt, + LCID lcid, DISPID *ids) +{ + ok(name_cnt == 1, "name_cnt = %u\n", name_cnt); + if(!wcscmp(names[0], L"testCall")) { + *ids = 1; + return S_OK; + } + + CHECK_EXPECT2(GetIDsOfNames); + return DISP_E_UNKNOWNNAME; +} + +static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID id, REFIID riid, LCID lcid, WORD flags, + DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, UINT *err) +{ + CHECK_EXPECT(testCall); + ok(id == 1, "id = %u\n", id); + ok(flags == DISPATCH_METHOD, "flags = %x\n", flags); + ok(!dp->cArgs, "cArgs = %u\n", dp->cArgs); + ok(!res, "res = %p\n", res); + return S_OK; +} + +static const IDispatchVtbl dispatch_vtbl = { + Dispatch_QueryInterface, + Dispatch_AddRef, + Dispatch_Release, + Dispatch_GetTypeInfoCount, + Dispatch_GetTypeInfo, + Dispatch_GetIDsOfNames, + Dispatch_Invoke +}; + +static IDispatch dispatch_object = { &dispatch_vtbl }; + +static const IDispatchVtbl global_named_item_vtbl = { + Dispatch_QueryInterface, + global_AddRef, + global_Release, + Dispatch_GetTypeInfoCount, + Dispatch_GetTypeInfo, + Dispatch_GetIDsOfNames, + Dispatch_Invoke +}; + +static IDispatch global_named_item = { &global_named_item_vtbl }; + +static const IDispatchVtbl visible_named_item_vtbl = { + Dispatch_QueryInterface, + visible_AddRef, + visible_Release, + Dispatch_GetTypeInfoCount, + Dispatch_GetTypeInfo, + Dispatch_GetIDsOfNames, + Dispatch_Invoke +}; + +static IDispatch visible_named_item = { &visible_named_item_vtbl }; + +static const IDispatchVtbl visible_code_named_item_vtbl = { + Dispatch_QueryInterface, + visible_code_AddRef, + visible_code_Release, + Dispatch_GetTypeInfoCount, + Dispatch_GetTypeInfo, + Dispatch_GetIDsOfNames, + Dispatch_Invoke +}; + +static IDispatch visible_code_named_item = { &visible_code_named_item_vtbl }; + static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) { *ppv = NULL; @@ -145,7 +289,32 @@ static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *p static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) { - ok(0, "unexpected call\n"); + ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "dwReturnMask = %x\n", dwReturnMask); + if(!wcscmp(pstrName, L"globalItem")) { + CHECK_EXPECT(GetItemInfo_global); + IDispatch_AddRef(&global_named_item); + *ppiunkItem = (IUnknown*)&global_named_item; + return S_OK; + } + if(!wcscmp(pstrName, L"globalCodeItem")) { + CHECK_EXPECT(GetItemInfo_global_code); + IDispatch_AddRef(&dispatch_object); + *ppiunkItem = (IUnknown*)&dispatch_object; + return S_OK; + } + if(!wcscmp(pstrName, L"visibleItem")) { + CHECK_EXPECT(GetItemInfo_visible); + IDispatch_AddRef(&visible_named_item); + *ppiunkItem = (IUnknown*)&visible_named_item; + return S_OK; + } + if(!wcscmp(pstrName, L"visibleCodeItem")) { + CHECK_EXPECT(GetItemInfo_visible_code); + IDispatch_AddRef(&visible_code_named_item); + *ppiunkItem = (IUnknown*)&visible_code_named_item; + return S_OK; + } + ok(0, "unexpected call %s\n", wine_dbgstr_w(pstrName)); return E_NOTIMPL; }
@@ -192,8 +361,8 @@ static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, S
static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + CHECK_EXPECT(OnScriptError); + return S_OK; }
static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) @@ -263,14 +432,14 @@ static void test_script_dispatch(IDispatchEx *dispex) VariantClear(&v); }
-static IDispatchEx *get_script_dispatch(IActiveScript *script) +static IDispatchEx *get_script_dispatch(IActiveScript *script, const WCHAR *item_name) { IDispatchEx *dispex; IDispatch *disp; HRESULT hres;
disp = (void*)0xdeadbeef; - hres = IActiveScript_GetScriptDispatch(script, NULL, &disp); + hres = IActiveScript_GetScriptDispatch(script, item_name, &disp); ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres);
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); @@ -512,7 +681,7 @@ static void test_jscript(void) hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); ok(hres == E_UNEXPECTED, "SetScriptSite failed: %08x, expected E_UNEXPECTED\n", hres);
- dispex = get_script_dispatch(script); + dispex = get_script_dispatch(script, NULL); test_script_dispatch(dispex);
SET_EXPECT(OnStateChange_STARTED); @@ -656,7 +825,7 @@ static void test_jscript_uninitializing(void)
test_state(script, SCRIPTSTATE_CONNECTED);
- dispex = get_script_dispatch(script); + dispex = get_script_dispatch(script, NULL); ok(dispex != NULL, "dispex == NULL\n"); IDispatchEx_Release(dispex);
@@ -741,7 +910,7 @@ static void test_code_persistence(void) ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr);
/* Pending code does not add identifiers to the global scope */ - dispex = get_script_dispatch(script); + dispex = get_script_dispatch(script, NULL); id = 0; get_disp_id(dispex, L"x", DISP_E_UNKNOWNNAME, &id); ok(id == -1, "id = %d, expected -1\n", id); @@ -780,7 +949,7 @@ static void test_code_persistence(void) CHECK_CALLED_MULTI(OnLeaveScript, 2); test_state(script, SCRIPTSTATE_CONNECTED);
- dispex = get_script_dispatch(script); + dispex = get_script_dispatch(script, NULL); id = 0; get_disp_id(dispex, L"x", DISP_E_UNKNOWNNAME, &id); ok(id == -1, "id = %d, expected -1\n", id); @@ -826,7 +995,7 @@ static void test_code_persistence(void) CHECK_CALLED(GetLCID); CHECK_CALLED(OnStateChange_INITIALIZED);
- dispex = get_script_dispatch(script); + dispex = get_script_dispatch(script, NULL); id = 0; get_disp_id(dispex, L"z", DISP_E_UNKNOWNNAME, &id); ok(id == -1, "id = %d, expected -1\n", id); @@ -842,7 +1011,7 @@ static void test_code_persistence(void) CHECK_CALLED(OnLeaveScript); test_state(script, SCRIPTSTATE_CONNECTED);
- dispex = get_script_dispatch(script); + dispex = get_script_dispatch(script, NULL); id = 0; get_disp_id(dispex, L"z", S_OK, &id); ok(id != -1, "id = -1\n"); @@ -905,7 +1074,7 @@ static void test_code_persistence(void) CHECK_CALLED(OnStateChange_CONNECTED); test_state(script, SCRIPTSTATE_CONNECTED);
- dispex = get_script_dispatch(script); + dispex = get_script_dispatch(script, NULL); id = 0; get_disp_id(dispex, L"y", DISP_E_UNKNOWNNAME, &id); ok(id == -1, "id = %d, expected -1\n", id); @@ -926,6 +1095,514 @@ static void test_code_persistence(void) CHECK_CALLED(OnStateChange_CLOSED); }
+static void test_named_items(void) +{ + static const WCHAR *global_idents[] = + { + L"ActiveXObject", + L"Array", + L"Boolean", + L"Date", + L"Enumerator", + L"Error", + L"eval", + L"EvalError", + L"Function", + L"Infinity", + L"Math", + L"NaN", + L"Number", + L"Object", + L"RangeError", + L"ReferenceError", + L"RegExp", + L"RegExpError", + L"String", + L"SyntaxError", + L"TypeError", + L"undefined", + L"URIError", + L"VBArray", + + L"CollectGarbage", + L"decodeURI", + L"decodeURIComponent", + L"encodeURI", + L"encodeURIComponent", + L"escape", + L"eval", + L"isFinite", + L"isNaN", + L"parseFloat", + L"parseInt", + L"ScriptEngine", + L"ScriptEngineBuildVersion", + L"ScriptEngineMajorVersion", + L"ScriptEngineMinorVersion", + L"unescape", + + L"global_this", + L"globalCode_this", + L"testFunc_global", + L"testVar_global" + }; + static const WCHAR *global_code_test[] = + { + L"testFunc_global();", + L"if(testVar_global != 5) throw new Error();", + L"var testObj = new testClassFunc();", + L"eval("testFunc_global();");", + L"if(Math.abs(-17) != 17) throw new Error();" + }; + static const WCHAR *context_idents[] = + { + L"testFunc", + L"testVar" + }; + static const WCHAR *context_code_test[] = + { + L"testFunc();", + L"if(testVar != 42) throw new Error();", + L"if(Math.abs(-testVar) != 42) throw new Error();" + }; + IDispatchEx *dispex, *dispex2; + IActiveScriptParse *parse; + IActiveScript *script; + IDispatch *disp; + VARIANT var; + unsigned i; + HRESULT hr; + DISPID id; + ULONG ref; + BSTR bstr; + + script = create_jscript(); + + hr = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parse); + ok(hr == S_OK, "Could not get IActiveScriptParse: %08x\n", hr); + + test_state(script, SCRIPTSTATE_UNINITIALIZED); + + hr = IActiveScript_AddNamedItem(script, L"visibleItem", SCRIPTITEM_ISVISIBLE); + ok(hr == E_UNEXPECTED, "AddNamedItem returned: %08x\n", hr); + hr = IActiveScript_AddNamedItem(script, L"globalItem", SCRIPTITEM_GLOBALMEMBERS); + ok(hr == E_UNEXPECTED, "AddNamedItem returned: %08x\n", hr); + hr = IActiveScript_AddNamedItem(script, L"codeOnlyItem", SCRIPTITEM_CODEONLY); + ok(hr == E_UNEXPECTED, "AddNamedItem returned: %08x\n", hr); + + SET_EXPECT(GetLCID); + hr = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr); + CHECK_CALLED(GetLCID); + + SET_EXPECT(GetItemInfo_global); + hr = IActiveScript_AddNamedItem(script, L"globalItem", SCRIPTITEM_GLOBALMEMBERS); + ok(hr == S_OK, "AddNamedItem failed: %08x\n", hr); + CHECK_CALLED(GetItemInfo_global); + + hr = IActiveScript_AddNamedItem(script, L"visibleItem", SCRIPTITEM_ISVISIBLE); + ok(hr == S_OK, "AddNamedItem failed: %08x\n", hr); + hr = IActiveScript_AddNamedItem(script, L"visibleCodeItem", SCRIPTITEM_ISVISIBLE | SCRIPTITEM_CODEONLY); + ok(hr == S_OK, "AddNamedItem failed: %08x\n", hr); + hr = IActiveScript_AddNamedItem(script, L"codeOnlyItem", SCRIPTITEM_CODEONLY); + ok(hr == S_OK, "AddNamedItem failed: %08x\n", hr); + + ok(global_named_item_ref > 0, "global_named_item_ref = %u\n", global_named_item_ref); + ok(visible_named_item_ref == 0, "visible_named_item_ref = %u\n", visible_named_item_ref); + ok(visible_code_named_item_ref == 0, "visible_code_named_item_ref = %u\n", visible_code_named_item_ref); + + hr = IActiveScript_GetScriptDispatch(script, L"noContext", &disp); + ok(hr == E_INVALIDARG, "GetScriptDispatch returned: %08x\n", hr); + hr = IActiveScript_GetScriptDispatch(script, L"codeONLYItem", &disp); + ok(hr == E_INVALIDARG, "GetScriptDispatch returned: %08x\n", hr); + + SET_EXPECT(GetItemInfo_global_code); + hr = IActiveScript_AddNamedItem(script, L"globalCodeItem", SCRIPTITEM_GLOBALMEMBERS | SCRIPTITEM_CODEONLY); + ok(hr == S_OK, "AddNamedItem failed: %08x\n", hr); + CHECK_CALLED(GetItemInfo_global_code); + + dispex = get_script_dispatch(script, NULL); + dispex2 = get_script_dispatch(script, L"globalItem"); + ok(dispex == dispex2, "get_script_dispatch returned different dispatch objects.\n"); + IDispatchEx_Release(dispex2); + dispex2 = get_script_dispatch(script, L"globalCodeItem"); + ok(dispex == dispex2, "get_script_dispatch returned different dispatch objects.\n"); + IDispatchEx_Release(dispex2); + dispex2 = get_script_dispatch(script, L"codeOnlyItem"); + ok(dispex != dispex2, "get_script_dispatch returned same dispatch objects.\n"); + + SET_EXPECT(OnStateChange_INITIALIZED); + hr = IActiveScriptParse_InitNew(parse); + ok(hr == S_OK, "InitNew failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_INITIALIZED); + + SET_EXPECT(OnStateChange_CONNECTED); + hr = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_CONNECTED); + + SET_EXPECT(testCall); + parse_script(parse, L"testCall();"); + CHECK_CALLED(testCall); + + SET_EXPECT(GetItemInfo_visible); + SET_EXPECT(testCall); + parse_script(parse, L"visibleItem.testCall();"); + CHECK_CALLED(GetItemInfo_visible); + CHECK_CALLED(testCall); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testCall); + hr = IActiveScriptParse_ParseScriptText(parse, L"testCall();", L"visibleCodeItem", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(testCall); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(GetIDsOfNames); + SET_EXPECT(OnScriptError); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"codeOnlyItem();", L"codeOnlyItem", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(FAILED(hr), "ParseScriptText returned: %08x\n", hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(GetIDsOfNames); + CHECK_CALLED(OnScriptError); + CHECK_CALLED(OnLeaveScript); + + hr = IActiveScript_GetScriptDispatch(script, L"visibleCodeItem", &disp); + ok(hr == S_OK, "GetScriptDispatch returned: %08x\n", hr); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"this", L"visibleCodeItem", NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == disp, + "Unexpected 'this': V_VT = %d, V_DISPATCH = %p\n", V_VT(&var), V_DISPATCH(&var)); + VariantClear(&var); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + IDispatch_Release(disp); + + SET_EXPECT(GetItemInfo_visible_code); + SET_EXPECT(testCall); + parse_script(parse, L"visibleCodeItem.testCall();"); + CHECK_CALLED(GetItemInfo_visible_code); + CHECK_CALLED(testCall); + + ok(global_named_item_ref > 0, "global_named_item_ref = %u\n", global_named_item_ref); + ok(visible_named_item_ref > 0, "visible_named_item_ref = %u\n", visible_named_item_ref); + ok(visible_code_named_item_ref > 0, "visible_code_named_item_ref = %u\n", visible_code_named_item_ref); + + SET_EXPECT(testCall); + parse_script(parse, L"visibleItem.testCall();"); + CHECK_CALLED(testCall); + + hr = IActiveScriptParse_ParseScriptText(parse, L"function testFunc() { }", L"CodeOnlyItem", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == E_INVALIDARG, "ParseScriptText returned: %08x\n", hr); + SET_EXPECT(OnEnterScript); + SET_EXPECT(GetIDsOfNames); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"" + "var global_this = 0;\n" + "var globalCode_this = 0;\n" + "function testFunc_global() { }\n" + "var testVar_global = 10;\n" + "function testClassFunc() { this.x = 10; }\n", + NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISPERSISTENT, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(GetIDsOfNames); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"function testFunc() { }\n", L"codeOnlyItem", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"" + "var testVar = 42;\n" + "testVar_global = 5;\n", + L"codeOnlyItem", NULL, NULL, 0, 0, SCRIPTTEXT_ISPERSISTENT, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"global_this = this;\n", L"globalItem", NULL, NULL, 0, 0, SCRIPTTEXT_ISPERSISTENT, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"globalCode_this = this;\n", L"globalCodeItem", NULL, NULL, 0, 0, SCRIPTTEXT_ISPERSISTENT, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + for (i = 0; i < ARRAY_SIZE(global_idents); i++) + { + bstr = SysAllocString(global_idents[i]); + id = 0; + hr = IDispatchEx_GetDispID(dispex, bstr, 0, &id); + ok(hr == S_OK, "GetDispID(%s) returned %08x\n", wine_dbgstr_w(global_idents[i]), hr); + ok(id != -1, "[%s] id = -1\n", wine_dbgstr_w(global_idents[i])); + id = 0; + hr = IDispatchEx_GetDispID(dispex2, bstr, 0, &id); + ok(hr == DISP_E_UNKNOWNNAME, "GetDispID(%s) returned %08x\n", wine_dbgstr_w(global_idents[i]), hr); + ok(id == -1, "[%s] id = %d, expected -1\n", wine_dbgstr_w(global_idents[i]), id); + SysFreeString(bstr); + } + for (i = 0; i < ARRAY_SIZE(context_idents); i++) + { + bstr = SysAllocString(context_idents[i]); + id = 0; + hr = IDispatchEx_GetDispID(dispex, bstr, 0, &id); + ok(hr == DISP_E_UNKNOWNNAME, "GetDispID(%s) returned %08x\n", wine_dbgstr_w(context_idents[i]), hr); + ok(id == -1, "[%s] id = %d, expected -1\n", wine_dbgstr_w(context_idents[i]), id); + id = 0; + hr = IDispatchEx_GetDispID(dispex2, bstr, 0, &id); + ok(hr == S_OK, "GetDispID(%s) returned %08x\n", wine_dbgstr_w(context_idents[i]), hr); + ok(id != -1, "[%s] id = -1\n", wine_dbgstr_w(context_idents[i])); + SysFreeString(bstr); + } + + for (i = 0; i < ARRAY_SIZE(global_code_test); i++) + { + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, global_code_test[i], NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText(%s) failed: %08x\n", wine_dbgstr_w(global_code_test[i]), hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(GetIDsOfNames); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, global_code_test[i], L"codeOnlyItem", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText(%s) failed: %08x\n", wine_dbgstr_w(global_code_test[i]), hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + } + for (i = 0; i < ARRAY_SIZE(context_code_test); i++) + { + SET_EXPECT(OnEnterScript); + SET_EXPECT(GetIDsOfNames); + SET_EXPECT(OnScriptError); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, context_code_test[i], NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(FAILED(hr), "ParseScriptText(%s) returned: %08x\n", wine_dbgstr_w(context_code_test[i]), hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(GetIDsOfNames); + CHECK_CALLED(OnScriptError); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, context_code_test[i], L"codeOnlyItem", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText(%s) failed: %08x\n", wine_dbgstr_w(context_code_test[i]), hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + } + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"this", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == &global_named_item, + "Unexpected 'this': V_VT = %d, V_DISPATCH = %p\n", V_VT(&var), V_DISPATCH(&var)); + VariantClear(&var); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"this", L"visibleItem", NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == &visible_named_item, + "Unexpected 'this': V_VT = %d, V_DISPATCH = %p\n", V_VT(&var), V_DISPATCH(&var)); + VariantClear(&var); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"this", L"codeOnlyItem", NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == (IDispatch*)dispex2, + "Unexpected 'this': V_VT = %d, V_DISPATCH = %p\n", V_VT(&var), V_DISPATCH(&var)); + VariantClear(&var); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"globalCode_this", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == &global_named_item, + "Unexpected 'this': V_VT = %d, V_DISPATCH = %p\n", V_VT(&var), V_DISPATCH(&var)); + VariantClear(&var); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + IDispatchEx_Release(dispex2); + IDispatchEx_Release(dispex); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_UNINITIALIZED); + hr = IActiveScript_SetScriptState(script, 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(script); + + ok(global_named_item_ref == 0, "global_named_item_ref = %u\n", global_named_item_ref); + ok(visible_named_item_ref == 0, "visible_named_item_ref = %u\n", visible_named_item_ref); + ok(visible_code_named_item_ref == 0, "visible_code_named_item_ref = %u\n", visible_code_named_item_ref); + + hr = IActiveScript_GetScriptDispatch(script, L"codeOnlyItem", &disp); + ok(hr == E_UNEXPECTED, "hr = %08x, expected E_UNEXPECTED\n", hr); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hr = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + hr = IActiveScript_AddNamedItem(script, L"codeOnlyItem", SCRIPTITEM_CODEONLY); + ok(hr == S_OK, "AddNamedItem failed: %08x\n", hr); + + SET_EXPECT(OnStateChange_CONNECTED); + SET_EXPECT_MULTI(OnEnterScript, 4); + SET_EXPECT_MULTI(OnLeaveScript, 4); + hr = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_CONNECTED); + CHECK_CALLED_MULTI(OnEnterScript, 4); + CHECK_CALLED_MULTI(OnLeaveScript, 4); + test_state(script, SCRIPTSTATE_CONNECTED); + + dispex = get_script_dispatch(script, NULL); + for (i = 0; i < ARRAY_SIZE(global_idents); i++) + { + bstr = SysAllocString(global_idents[i]); + id = 0; + hr = IDispatchEx_GetDispID(dispex, bstr, 0, &id); + ok(hr == S_OK, "GetDispID(%s) returned %08x\n", wine_dbgstr_w(global_idents[i]), hr); + ok(id != -1, "[%s] id = -1\n", wine_dbgstr_w(global_idents[i])); + SysFreeString(bstr); + } + for (i = 0; i < ARRAY_SIZE(context_idents); i++) + { + bstr = SysAllocString(context_idents[i]); + id = 0; + hr = IDispatchEx_GetDispID(dispex, bstr, 0, &id); + ok(hr == DISP_E_UNKNOWNNAME, "GetDispID(%s) returned %08x\n", wine_dbgstr_w(context_idents[i]), hr); + ok(id == -1, "[%s] id = %d, expected -1\n", wine_dbgstr_w(context_idents[i]), id); + SysFreeString(bstr); + } + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"global_this", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == (IDispatch*)dispex, + "Unexpected 'this': V_VT = %d, V_DISPATCH = %p\n", V_VT(&var), V_DISPATCH(&var)); + VariantClear(&var); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"globalCode_this", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &var, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + ok(V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == (IDispatch*)dispex, + "Unexpected 'this': V_VT = %d, V_DISPATCH = %p\n", V_VT(&var), V_DISPATCH(&var)); + VariantClear(&var); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, L"global_this = 0; globalCode_this = 0;\n", NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + IDispatchEx_Release(dispex); + + dispex = get_script_dispatch(script, L"codeOnlyItem"); + for (i = 0; i < ARRAY_SIZE(global_idents); i++) + { + bstr = SysAllocString(global_idents[i]); + id = 0; + hr = IDispatchEx_GetDispID(dispex, bstr, 0, &id); + ok(hr == DISP_E_UNKNOWNNAME, "GetDispID(%s) returned %08x\n", wine_dbgstr_w(global_idents[i]), hr); + ok(id == -1, "[%s] id = %d, expected -1\n", wine_dbgstr_w(global_idents[i]), id); + SysFreeString(bstr); + } + for (i = 0; i < ARRAY_SIZE(context_idents); i++) + { + bstr = SysAllocString(context_idents[i]); + id = 0; + hr = IDispatchEx_GetDispID(dispex, bstr, 0, &id); + ok(hr == DISP_E_UNKNOWNNAME, "GetDispID(%s) returned %08x\n", wine_dbgstr_w(context_idents[i]), hr); + ok(id == -1, "[%s] id = %d, expected -1\n", wine_dbgstr_w(context_idents[i]), id); + SysFreeString(bstr); + } + IDispatchEx_Release(dispex); + + for (i = 0; i < ARRAY_SIZE(global_code_test); i++) + { + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, global_code_test[i], NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText(%s) failed: %08x\n", wine_dbgstr_w(global_code_test[i]), hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, global_code_test[i], L"codeOnlyItem", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hr == S_OK, "ParseScriptText(%s) failed: %08x\n", wine_dbgstr_w(global_code_test[i]), hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + } + for (i = 0; i < ARRAY_SIZE(context_code_test); i++) + { + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnScriptError); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, context_code_test[i], NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(FAILED(hr), "ParseScriptText(%s) returned: %08x\n", wine_dbgstr_w(context_code_test[i]), hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnScriptError); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnScriptError); + SET_EXPECT(OnLeaveScript); + hr = IActiveScriptParse_ParseScriptText(parse, context_code_test[i], L"codeOnlyItem", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(FAILED(hr), "ParseScriptText(%s) returned: %08x\n", wine_dbgstr_w(context_code_test[i]), hr); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnScriptError); + CHECK_CALLED(OnLeaveScript); + } + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_CLOSED); + hr = IActiveScript_Close(script); + ok(hr == S_OK, "Close failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_CLOSED); + + ok(global_named_item_ref == 0, "global_named_item_ref = %u\n", global_named_item_ref); + ok(visible_named_item_ref == 0, "visible_named_item_ref = %u\n", visible_named_item_ref); + ok(visible_code_named_item_ref == 0, "visible_code_named_item_ref = %u\n", visible_code_named_item_ref); + + test_state(script, SCRIPTSTATE_CLOSED); + IActiveScriptParse_Release(parse); + + ref = IActiveScript_Release(script); + ok(!ref, "ref = %d\n", ref); +} + static void test_typeinfo(const WCHAR *parse_func_name) { static struct @@ -1043,7 +1720,7 @@ static void test_typeinfo(const WCHAR *parse_func_name) else { parse_script(parser, source); - disp = get_script_dispatch(script); + disp = get_script_dispatch(script, NULL); }
hr = IDispatchEx_QueryInterface(disp, &IID_ITypeInfo, (void**)&typeinfo); @@ -1406,6 +2083,7 @@ START_TEST(jscript) test_jscript_uninitializing(); test_aggregation(); test_code_persistence(); + test_named_items(); test_typeinfo(NULL); test_typeinfo(L"some_func_name");
On 02.03.2020 14:39, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescugabrielopcode@gmail.com
dlls/jscript/tests/jscript.c | 704 ++++++++++++++++++++++++++++++++++- 1 file changed, 691 insertions(+), 13 deletions(-)
I added some todo_wines and sent it. There is no reason to wait for the rest series done. I had to remove a few minor tests that would otherwise require extra code to deal with missing Wine, feel free to resend them once implementation part is fixed.
Thanks,
Jacek