Jacek Caban : jscript: Allow calling eval function from external code.

Alexandre Julliard julliard at winehq.org
Mon May 20 15:50:49 CDT 2019


Module: wine
Branch: master
Commit: aac2110e8ff93d74ac99ab3bb78a47e1ea491cfa
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=aac2110e8ff93d74ac99ab3bb78a47e1ea491cfa

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon May 20 21:05:25 2019 +0200

jscript: Allow calling eval function from external code.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/jscript/global.c    |  13 ++---
 dlls/jscript/tests/run.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+), 9 deletions(-)

diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c
index 92b146c..cdabf6f 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 c8a143b..e48f748 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, &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(
         "?",




More information about the wine-cvs mailing list