diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 92b146c83ac..cdabf6f6ff5 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -181,7 +181,7 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - call_frame_t *frame; + call_frame_t *frame = ctx->call_ctx; DWORD exec_flags = EXEC_EVAL; bytecode_t *code; const WCHAR *src; @@ -201,11 +201,6 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a return S_OK; } - if(!(frame = ctx->call_ctx)) { - FIXME("No active exec_ctx\n"); - return E_UNEXPECTED; - } - src = jsstr_flatten(get_string(argv[0])); if(!src) return E_OUTOFMEMORY; @@ -217,12 +212,12 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a return throw_syntax_error(ctx, hres, NULL); } - if(frame->flags & EXEC_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->scope, - frame->this_obj, NULL, frame->variable_obj, 0, NULL, r); + 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); release_bytecode(code); return hres; } diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index c8a143bebad..e48f7484d06 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -91,6 +91,7 @@ DEFINE_EXPECT(global_notexists_d); DEFINE_EXPECT(global_propargput_d); DEFINE_EXPECT(global_propargput_i); DEFINE_EXPECT(global_testargtypes_i); +DEFINE_EXPECT(global_calleval_i); DEFINE_EXPECT(puredisp_prop_d); DEFINE_EXPECT(puredisp_noprop_d); DEFINE_EXPECT(puredisp_value); @@ -149,6 +150,7 @@ DEFINE_EXPECT(BindHandler); #define DISPID_GLOBAL_GETSCRIPTSTATE 0x101c #define DISPID_GLOBAL_BINDEVENTHANDLER 0x101d #define DISPID_GLOBAL_TESTENUMOBJ 0x101e +#define DISPID_GLOBAL_CALLEVAL 0x101f #define DISPID_GLOBAL_TESTPROPDELETE 0x2000 #define DISPID_GLOBAL_TESTNOPROPDELETE 0x2001 @@ -988,6 +990,11 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD return S_OK; } + if(!strcmp_wa(bstrName, "callEval")) { + *pid = DISPID_GLOBAL_CALLEVAL; + return S_OK; + } + if(strict_dispid_check && strcmp_wa(bstrName, "t")) ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName)); return DISP_E_UNKNOWNNAME; @@ -1492,6 +1499,43 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, return S_OK; } + + case DISPID_GLOBAL_CALLEVAL: { + IDispatchEx *eval_func; + DISPPARAMS params; + VARIANT arg, res; + HRESULT hres; + + CHECK_EXPECT(global_calleval_i); + + 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)); + hres = IDispatch_QueryInterface(V_DISPATCH(pdp->rgvarg), &IID_IDispatchEx, (void**)&eval_func); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + + params.rgvarg = &arg; + params.rgdispidNamedArgs = NULL; + params.cArgs = 1; + params.cNamedArgs = 0; + V_VT(&arg) = VT_BSTR; + + V_BSTR(&arg) = a2bstr("var x = 5; v"); + V_VT(&res) = VT_ERROR; + hres = IDispatchEx_InvokeEx(eval_func, DISPID_VALUE, 0, DISPATCH_METHOD, ¶ms, &res, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&res) == VT_I4, "eval returned type %u\n", V_VT(&res)); + ok(V_I4(&res) == 2, "eval returned %d\n", V_I4(&res)); + SysFreeString(V_BSTR(&arg)); + IDispatchEx_Release(eval_func); + return S_OK; + } } ok(0, "unexpected call %x\n", id); @@ -2492,6 +2536,107 @@ static void test_invokeex(void) IActiveScript_Release(script); } +static void test_eval(void) +{ + IActiveScriptParse *parser; + IDispatchEx *script_dispex; + IDispatch *script_disp; + IActiveScript *engine; + VARIANT arg, res; + DISPPARAMS params; + DISPID id, v_id; + BSTR str; + HRESULT hres; + + engine = create_script(); + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + SET_EXPECT(GetItemInfo_testVal); + hres = IActiveScript_AddNamedItem(engine, test_valW, + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + CHECK_CALLED(GetItemInfo_testVal); + + 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"); + + hres = IDispatch_QueryInterface(script_disp, &IID_IDispatchEx, (void**)&script_dispex); + ok(hres == S_OK, "Coult not get IDispatchEx iface: %08x\n", hres); + IDispatch_Release(script_disp); + + str = a2bstr("eval"); + hres = IDispatchEx_GetDispID(script_dispex, str, 0, &id); + ok(hres == S_OK, "Could not get eval dispid: %08x\n", hres); + SysFreeString(str); + + params.rgvarg = &arg; + params.rgdispidNamedArgs = NULL; + params.cArgs = 1; + params.cNamedArgs = 0; + V_VT(&arg) = VT_BSTR; + + V_BSTR(&arg) = a2bstr("var v = 1;"); + V_VT(&res) = VT_ERROR; + hres = IDispatchEx_InvokeEx(script_dispex, id, 0, DISPATCH_METHOD, ¶ms, &res, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&res) == VT_EMPTY, "eval returned type %u\n", V_VT(&res)); + SysFreeString(V_BSTR(&arg)); + + V_BSTR(&arg) = a2bstr("v"); + V_VT(&res) = VT_ERROR; + hres = IDispatchEx_InvokeEx(script_dispex, id, 0, DISPATCH_METHOD, ¶ms, &res, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&res) == VT_I4, "eval returned type %u\n", V_VT(&res)); + ok(V_I4(&res) == 1, "eval returned %d\n", V_I4(&res)); + SysFreeString(V_BSTR(&arg)); + + str = a2bstr("v"); + hres = IDispatchEx_GetDispID(script_dispex, str, 0, &v_id); + ok(hres == S_OK, "Could not get v dispid: %08x\n", hres); + SysFreeString(str); + + params.rgvarg = NULL; + params.cArgs = 0; + V_VT(&res) = VT_ERROR; + hres = IDispatchEx_InvokeEx(script_dispex, v_id, 0, DISPATCH_PROPERTYGET, ¶ms, &res, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&res) == VT_I4, "eval returned type %u\n", V_VT(&res)); + ok(V_I4(&res) == 1, "eval returned %d\n", V_I4(&res)); + + SET_EXPECT(global_calleval_i); + str = a2bstr("(function(){" + " var v = 2;" + " callEval(eval);" + " ok(x === 5, 'x = ' + x);" + "})();"); + hres = IActiveScriptParse_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + SysFreeString(str); + CHECK_CALLED(global_calleval_i); + + str = a2bstr("x"); + hres = IDispatchEx_GetDispID(script_dispex, str, 0, &id); + ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(x) returned %08x\n", hres); + SysFreeString(str); + + IDispatchEx_Release(script_dispex); + IActiveScriptParse_Release(parser); + IActiveScript_Close(engine); + IActiveScript_Release(engine); +} + struct bom_test { WCHAR str[1024]; @@ -2877,6 +3022,7 @@ static BOOL run_tests(void) test_script_exprs(); test_invokeex(); + test_eval(); parse_script_with_error_a( "?",