jscript: Allow calling eval function from external code.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-05-20 21:05:25 +02:00 committed by Alexandre Julliard
parent d2b32bac5c
commit aac2110e8f
2 changed files with 150 additions and 9 deletions

View File

@ -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;
}

View File

@ -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, &params, &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, &params, &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, &params, &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, &params, &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(
"?",