diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index a3007fc3941..cecfd62b606 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -178,7 +178,8 @@ void scope_release(scope_chain_t *scope) heap_free(scope); } -HRESULT create_exec_ctx(IDispatch *this_obj, DispatchEx *var_disp, scope_chain_t *scope, exec_ctx_t **ret) +HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, DispatchEx *var_disp, + scope_chain_t *scope, exec_ctx_t **ret) { exec_ctx_t *ctx; @@ -188,8 +189,13 @@ HRESULT create_exec_ctx(IDispatch *this_obj, DispatchEx *var_disp, scope_chain_t ctx->ref = 1; - IDispatch_AddRef(this_obj); - ctx->this_obj = this_obj; + if(this_obj) + ctx->this_obj = this_obj; + else if(script_ctx->host_global) + ctx->this_obj = script_ctx->host_global; + else + ctx->this_obj = (IDispatch*)_IDispatchEx_(script_ctx->global); + IDispatch_AddRef(ctx->this_obj); IDispatchEx_AddRef(_IDispatchEx_(var_disp)); ctx->var_disp = var_disp; @@ -537,21 +543,15 @@ static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, js } } - hres = jsdisp_get_id(ctx->parser->script->script_disp, identifier, 0, &id); - if(SUCCEEDED(hres)) { - exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->script_disp), id); - return S_OK; - } - if(lookup_global_members(ctx->parser->script, identifier, ret)) return S_OK; if(flags & EXPR_NEWREF) { - hres = jsdisp_get_id(ctx->parser->script->script_disp, identifier, fdexNameEnsure, &id); + hres = jsdisp_get_id(ctx->parser->script->global, identifier, fdexNameEnsure, &id); if(FAILED(hres)) return hres; - exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->script_disp), id); + exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id); return S_OK; } diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 09394cefa12..386f38b51fd 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -116,7 +116,7 @@ static inline void exec_addref(exec_ctx_t *ctx) } void exec_release(exec_ctx_t*); -HRESULT create_exec_ctx(IDispatch*,DispatchEx*,scope_chain_t*,exec_ctx_t**); +HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,DispatchEx*,scope_chain_t*,exec_ctx_t**); HRESULT exec_source(exec_ctx_t*,parser_ctx_t*,source_elements_t*,jsexcept_t*,VARIANT*); typedef struct _statement_t statement_t; diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index cbdc08b953e..b0fb79d711d 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -210,7 +210,7 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis hres = scope_push(function->scope_chain, var_disp, &scope); if(SUCCEEDED(hres)) { - hres = create_exec_ctx(this_obj, var_disp, scope, &exec_ctx); + hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx); scope_release(scope); } if(FAILED(hres)) @@ -222,17 +222,6 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis return hres; } -static HRESULT invoke_function(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) -{ - IDispatch *this_obj; - - if(!(this_obj = get_this(dp))) - this_obj = (IDispatch*)_IDispatchEx_(ctx->script_disp); - - return invoke_source(ctx, function, this_obj, dp, retv, ei, caller); -} - static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { @@ -254,18 +243,18 @@ static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, return S_OK; } -static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, WORD flags, DISPPARAMS *dp, +static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - IDispatch *this_disp; vdisp_t vthis; HRESULT hres; - this_disp = get_this(dp); if(this_disp) set_disp(&vthis, this_disp); + else if(ctx->host_global) + set_disp(&vthis, ctx->host_global); else - set_jsdisp(&vthis, ctx->script_disp); + set_jsdisp(&vthis, ctx->global); hres = function->value_proc(ctx, &vthis, flags, dp, retv, ei, caller); @@ -276,24 +265,10 @@ static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *args, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - HRESULT hres; + if(function->value_proc) + return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, args, retv, ei, caller); - if(function->value_proc) { - vdisp_t vthis; - - if(this_obj) - set_disp(&vthis, this_obj); - else - set_jsdisp(&vthis, ctx->script_disp); - - hres = function->value_proc(ctx, &vthis, DISPATCH_METHOD, args, retv, ei, caller); - vdisp_release(&vthis); - }else { - hres = invoke_source(ctx, function, this_obj ? this_obj : (IDispatch*)_IDispatchEx_(ctx->script_disp), - args, retv, ei, caller); - } - - return hres; + return invoke_source(ctx, function, this_obj, args, retv, ei, caller); } static HRESULT function_to_string(FunctionInstance *function, BSTR *ret) @@ -506,9 +481,9 @@ HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAM switch(flags) { case DISPATCH_METHOD: if(function->value_proc) - return invoke_value_proc(ctx, function, flags, dp, retv, ei, caller); + return invoke_value_proc(ctx, function, get_this(dp), flags, dp, retv, ei, caller); - return invoke_function(ctx, function, dp, retv, ei, caller); + return invoke_source(ctx, function, get_this(dp), dp, retv, ei, caller); case DISPATCH_PROPERTYGET: { HRESULT hres; @@ -525,7 +500,7 @@ HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAM case DISPATCH_CONSTRUCT: if(function->value_proc) - return invoke_value_proc(ctx, function, flags, dp, retv, ei, caller); + return invoke_value_proc(ctx, function, get_this(dp), flags, dp, retv, ei, caller); return invoke_constructor(ctx, function, dp, retv, ei, caller); diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 0771e9badb7..1efe8e13d0f 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -96,7 +96,7 @@ static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx) VARIANT var; HRESULT hres; - hres = create_exec_ctx((IDispatch*)_IDispatchEx_(This->ctx->script_disp), This->ctx->script_disp, NULL, &exec_ctx); + hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, &exec_ctx); if(FAILED(hres)) return hres; @@ -148,12 +148,6 @@ static HRESULT set_ctx_site(JScript *This) This->ctx->lcid = This->lcid; - if(!This->ctx->script_disp) { - hres = create_dispex(This->ctx, NULL, NULL, &This->ctx->script_disp); - if(FAILED(hres)) - return hres; - } - hres = init_global(This->ctx); if(FAILED(hres)) return hres; @@ -335,6 +329,11 @@ static HRESULT WINAPI JScript_Close(IActiveScript *iface) if(This->ctx->state == SCRIPTSTATE_DISCONNECTED) change_state(This, SCRIPTSTATE_INITIALIZED); + if(This->ctx->host_global) { + IDispatch_Release(This->ctx->host_global); + This->ctx->host_global = NULL; + } + if(This->ctx->named_items) { named_item_t *iter, *iter2; @@ -360,11 +359,6 @@ static HRESULT WINAPI JScript_Close(IActiveScript *iface) if (This->site) change_state(This, SCRIPTSTATE_CLOSED); - if(This->ctx->script_disp) { - jsdisp_release(This->ctx->script_disp); - This->ctx->script_disp = NULL; - } - if(This->ctx->global) { jsdisp_release(This->ctx->global); This->ctx->global = NULL; @@ -407,6 +401,11 @@ 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)); @@ -449,12 +448,12 @@ static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR if(!ppdisp) return E_POINTER; - if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_disp) { + if(This->thread_id != GetCurrentThreadId() || !This->ctx->global) { *ppdisp = NULL; return E_UNEXPECTED; } - *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->script_disp); + *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->global); IDispatch_AddRef(*ppdisp); return S_OK; } diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 8f9873cb9a6..bbf929dd631 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -264,7 +264,8 @@ struct _script_ctx_t { jsheap_t tmp_heap; - DispatchEx *script_disp; + IDispatch *host_global; + DispatchEx *global; DispatchEx *function_constr; DispatchEx *array_constr; diff --git a/dlls/jscript/tests/jscript.c b/dlls/jscript/tests/jscript.c index 9d9681c299b..e53fc2dcfd2 100644 --- a/dlls/jscript/tests/jscript.c +++ b/dlls/jscript/tests/jscript.c @@ -68,6 +68,18 @@ DEFINE_EXPECT(OnStateChange_INITIALIZED); DEFINE_EXPECT(OnEnterScript); DEFINE_EXPECT(OnLeaveScript); +static BSTR a2bstr(const char *str) +{ + BSTR ret; + int len; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len-1); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + + return ret; +} + #define test_state(s,ss) _test_state(__LINE__,s,ss) static void _test_state(unsigned line, IActiveScript *script, SCRIPTSTATE exstate) { @@ -195,6 +207,8 @@ static void test_script_dispatch(IActiveScript *script, BOOL initialized) { IDispatchEx *dispex; IDispatch *disp; + BSTR str; + DISPID id; HRESULT hres; disp = (void*)0xdeadbeef; @@ -214,6 +228,11 @@ static void test_script_dispatch(IActiveScript *script, BOOL initialized) IDispatch_Release(disp); ok(hres == S_OK, "Could not get IDispatchEx interface: %08x\n", hres); + str = a2bstr("ActiveXObject"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseSensitive, &id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + IDispatchEx_Release(dispex); } diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index 1cfee4f26b0..cf34b2f1abd 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -79,6 +79,8 @@ DEFINE_EXPECT(GetItemInfo_testVal); #define DISPID_GLOBAL_TESTOBJ 0x1006 #define DISPID_GLOBAL_NULL_BSTR 0x1007 #define DISPID_GLOBAL_NULL_DISP 0x1008 +#define DISPID_GLOBAL_TESTTHIS 0x1009 +#define DISPID_GLOBAL_TESTTHIS2 0x100a #define DISPID_TESTOBJ_PROP 0x2000 @@ -89,6 +91,7 @@ static const CHAR test_valA[] = "testVal"; static BOOL strict_dispid_check; static const char *test_name = "(null)"; +static IDispatch *script_disp; static BSTR a2bstr(const char *str) { @@ -325,6 +328,18 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD return DISP_E_UNKNOWNNAME; } + if(!strcmp_wa(bstrName, "testThis")) { + ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex); + *pid = DISPID_GLOBAL_TESTTHIS; + return S_OK; + } + + if(!strcmp_wa(bstrName, "testThis2")) { + ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex); + *pid = DISPID_GLOBAL_TESTTHIS2; + return S_OK; + } + if(strict_dispid_check) ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName)); return DISP_E_UNKNOWNNAME; @@ -492,6 +507,35 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, V_VT(pvarRes) = VT_DISPATCH; V_DISPATCH(pvarRes) = NULL; return S_OK; + + case DISPID_GLOBAL_TESTTHIS: + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes == NULL, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(arg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_DISPATCH(pdp->rgvarg) == (IDispatch*)iface, "disp != iface\n"); + + return S_OK; + + case DISPID_GLOBAL_TESTTHIS2: + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes == NULL, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(arg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_DISPATCH(pdp->rgvarg) != (IDispatch*)iface, "disp == iface\n"); + ok(V_DISPATCH(pdp->rgvarg) == script_disp, "disp != script_disp\n"); + + return S_OK; } ok(0, "unexpected call %x\n", id); @@ -625,7 +669,7 @@ static IActiveScript *create_script(void) return script; } -static void parse_script(BSTR script_str) +static void parse_script(DWORD flags, BSTR script_str) { IActiveScriptParse *parser; IActiveScript *engine; @@ -650,15 +694,21 @@ static void parse_script(BSTR script_str) ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); hres = IActiveScript_AddNamedItem(engine, testW, - SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|flags); ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED); ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + hres = IActiveScript_GetScriptDispatch(engine, NULL, &script_disp); + ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres); + ok(script_disp != NULL, "script_disp == NULL\n"); + ok(script_disp != (IDispatch*)&Global, "script_disp == Global\n"); + hres = IActiveScriptParse64_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + IDispatch_Release(script_disp); IActiveScript_Release(engine); IUnknown_Release(parser); } @@ -704,13 +754,18 @@ static HRESULT parse_htmlscript(BSTR script_str) return hres; } -static void parse_script_a(const char *src) +static void parse_script_af(DWORD flags, const char *src) { BSTR tmp = a2bstr(src); - parse_script(tmp); + parse_script(flags, tmp); SysFreeString(tmp); } +static void parse_script_a(const char *src) +{ + parse_script_af(SCRIPTITEM_GLOBALMEMBERS, src); +} + static HRESULT parse_htmlscript_a(const char *src) { HRESULT hres; @@ -766,7 +821,7 @@ static void run_from_file(const char *filename) strict_dispid_check = FALSE; if(script_str) - parse_script(script_str); + parse_script(SCRIPTITEM_GLOBALMEMBERS, script_str); SysFreeString(script_str); } @@ -793,7 +848,7 @@ static void run_from_res(const char *name) SET_EXPECT(global_success_d); SET_EXPECT(global_success_i); - parse_script(str); + parse_script(SCRIPTITEM_GLOBALMEMBERS, str); CHECK_CALLED(global_success_d); CHECK_CALLED(global_success_i); @@ -916,6 +971,21 @@ static void run_tests(void) parse_script_a("ok(String.prototype.concat.call(testObj, ' OK') === '1 OK', 'wrong concat result');"); CHECK_CALLED(testobj_value); + SET_EXPECT(global_propget_d); + SET_EXPECT(global_propget_i); + parse_script_a("this.testPropGet;"); + CHECK_CALLED(global_propget_d); + CHECK_CALLED(global_propget_i); + + SET_EXPECT(global_propget_d); + SET_EXPECT(global_propget_i); + parse_script_a("(function () { this.testPropGet; })();"); + CHECK_CALLED(global_propget_d); + CHECK_CALLED(global_propget_i); + + parse_script_a("testThis(this);"); + parse_script_a("(function () { testThis(this); })();"); + run_from_res("lang.js"); run_from_res("api.js"); run_from_res("regexp.js"); @@ -923,6 +993,9 @@ static void run_tests(void) test_isvisible(FALSE); test_isvisible(TRUE); + parse_script_af(0, "test.testThis2(this);"); + parse_script_af(0, "(function () { test.testThis2(this); })();"); + hres = parse_htmlscript_a("");