Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/jscript.c | 12 ++++++++++-- dlls/jscript/jscript.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 5e02d4f..5e9b153 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -143,6 +143,14 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *item_name, unsig return NULL; }
+void release_named_item(named_item_t *item) +{ + if(--item->ref) return; + + heap_free(item->name); + heap_free(item); +} + static inline JScriptError *impl_from_IActiveScriptError(IActiveScriptError *iface) { return CONTAINING_RECORD(iface, JScriptError, IActiveScriptError_iface); @@ -415,8 +423,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state)
if(iter->disp) IDispatch_Release(iter->disp); - heap_free(iter->name); - heap_free(iter); + release_named_item(iter); iter = iter2; }
@@ -833,6 +840,7 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, return E_OUTOFMEMORY; }
+ item->ref = 1; item->disp = disp; item->flags = dwFlags; item->name = heap_strdupW(pstrName); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 8297838..efd5a54 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -206,6 +206,7 @@ HRESULT builtin_set_const(script_ctx_t*,jsdisp_t*,jsval_t) DECLSPEC_HIDDEN;
typedef struct named_item_t { IDispatch *disp; + unsigned ref; DWORD flags; LPWSTR name;
@@ -213,6 +214,7 @@ typedef struct named_item_t { } named_item_t;
named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN; +void release_named_item(named_item_t*) DECLSPEC_HIDDEN;
typedef struct { const WCHAR *name;
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/jscript.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 5e9b153..8311eef 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -827,10 +827,10 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, return hres; }
- if(This->ctx->host_global) - IDispatch_Release(This->ctx->host_global); - IDispatch_AddRef(disp); - This->ctx->host_global = disp; + if(!This->ctx->host_global) { + IDispatch_AddRef(disp); + This->ctx->host_global = disp; + } }
item = heap_alloc(sizeof(*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: 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 | 80 ++++++++++++++++++++++++++++++++++++++++-- dlls/jscript/jscript.h | 2 ++ 7 files changed, 123 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 4e28b63..6b261e7 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -654,6 +654,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); @@ -1236,13 +1245,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) { @@ -2972,6 +2985,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); @@ -2994,6 +3016,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) { @@ -3005,7 +3029,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); @@ -3057,6 +3081,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 if(ctx->host_global) frame->this_obj = ctx->host_global; else diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index cad46e1..06ef500 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -180,6 +180,7 @@ struct _bytecode_t { heap_pool_t heap;
function_code_t global_code; + named_item_t *named_item;
WCHAR *source; UINT64 source_context; @@ -231,6 +232,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 8311eef..ebdd5c4 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,12 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *item_name, unsig
for(item = ctx->named_items; item; item = item->next) { if((item->flags & flags) == flags && !wcscmp(item->name, item_name)) { + if(!item->script_obj) { + if(item->flags & SCRIPTITEM_GLOBALMEMBERS) + return item; + 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 +398,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 +444,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state) /* FALLTHROUGH */ case SCRIPTSTATE_INITIALIZED: clear_script_queue(This); + release_persistent_script_objs(This);
if(This->ctx->host_global) { IDispatch_Release(This->ctx->host_global); @@ -423,6 +460,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state)
if(iter->disp) IDispatch_Release(iter->disp); + release_named_item_script_obj(iter); release_named_item(iter); iter = iter2; } @@ -843,6 +881,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) @@ -869,6 +908,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);
@@ -880,7 +920,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; } @@ -1001,6 +1048,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; @@ -1012,11 +1060,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; @@ -1093,6 +1154,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; @@ -1105,11 +1167,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 efd5a54..bf7a179 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 named_item_t *next; } 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;
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");