From 8c5f5b49eca0ea8e28698602c668606a6dacd736 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 13 Sep 2012 14:34:25 +0200 Subject: [PATCH] jscript: Added support for host objects being part of scope chain. --- dlls/jscript/engine.c | 28 ++++++++++++---------------- dlls/jscript/engine.h | 5 +++-- dlls/jscript/function.c | 2 +- dlls/jscript/tests/run.c | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index eb2adca5f3d..f7c7d1ac39f 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -268,7 +268,7 @@ static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id) IDispatch_AddRef(disp); } -HRESULT scope_push(scope_chain_t *scope, jsdisp_t *obj, scope_chain_t **ret) +HRESULT scope_push(scope_chain_t *scope, jsdisp_t *jsobj, IDispatch *obj, scope_chain_t **ret) { scope_chain_t *new_scope; @@ -278,7 +278,8 @@ HRESULT scope_push(scope_chain_t *scope, jsdisp_t *obj, scope_chain_t **ret) new_scope->ref = 1; - jsdisp_addref(obj); + IDispatch_AddRef(obj); + new_scope->jsobj = jsobj; new_scope->obj = obj; if(scope) { @@ -309,7 +310,7 @@ void scope_release(scope_chain_t *scope) if(scope->next) scope_release(scope->next); - jsdisp_release(scope->obj); + IDispatch_Release(scope->obj); heap_free(scope); } @@ -511,9 +512,12 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re TRACE("%s\n", debugstr_w(identifier)); for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) { - hres = jsdisp_get_id(scope->obj, identifier, 0, &id); + if(scope->jsobj) + hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id); + else + hres = disp_get_id(ctx, scope->obj, identifier, fdexNameImplicit, &id); if(SUCCEEDED(hres)) { - exprval_set_idref(ret, to_disp(scope->obj), id); + exprval_set_idref(ret, scope->obj, id); return S_OK; } } @@ -668,7 +672,6 @@ static HRESULT interp_forin(exec_ctx_t *ctx) static HRESULT interp_push_scope(exec_ctx_t *ctx) { IDispatch *disp; - jsdisp_t *obj; VARIANT *v; HRESULT hres; @@ -680,15 +683,8 @@ static HRESULT interp_push_scope(exec_ctx_t *ctx) if(FAILED(hres)) return hres; - obj = to_jsdisp(disp); - if(!obj) { - IDispatch_Release(disp); - FIXME("disp is not jsdisp\n"); - return E_NOTIMPL; - } - - hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain); - jsdisp_release(obj); + hres = scope_push(ctx->scope_chain, to_jsdisp(disp), disp, &ctx->scope_chain); + IDispatch_Release(disp); return hres; } @@ -2509,7 +2505,7 @@ static HRESULT unwind_exception(exec_ctx_t *ctx) if(FAILED(hres)) return hres; - hres = scope_push(ctx->scope_chain, scope_obj, &ctx->scope_chain); + hres = scope_push(ctx->scope_chain, scope_obj, to_disp(scope_obj), &ctx->scope_chain); jsdisp_release(scope_obj); }else { VARIANT v; diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index b3648af2ff8..22283aafff0 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -203,11 +203,12 @@ static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size) typedef struct _scope_chain_t { LONG ref; - jsdisp_t *obj; + jsdisp_t *jsobj; + IDispatch *obj; struct _scope_chain_t *next; } scope_chain_t; -HRESULT scope_push(scope_chain_t*,jsdisp_t*,scope_chain_t**) DECLSPEC_HIDDEN; +HRESULT scope_push(scope_chain_t*,jsdisp_t*,IDispatch*,scope_chain_t**) DECLSPEC_HIDDEN; void scope_release(scope_chain_t*) DECLSPEC_HIDDEN; static inline void scope_addref(scope_chain_t *scope) diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 23ce98c06c7..e7a011d4f71 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -182,7 +182,7 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis return hres; } - hres = scope_push(function->scope_chain, var_disp, &scope); + hres = scope_push(function->scope_chain, var_disp, to_disp(var_disp), &scope); if(SUCCEEDED(hres)) { hres = create_exec_ctx(ctx, this_obj, var_disp, scope, FALSE, &exec_ctx); scope_release(scope); diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index 4a9f36dcaa2..30a1f9c8fe3 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -88,6 +88,8 @@ DEFINE_EXPECT(puredisp_noprop_d); DEFINE_EXPECT(testobj_delete); DEFINE_EXPECT(testobj_value); DEFINE_EXPECT(testobj_prop_d); +DEFINE_EXPECT(testobj_withprop_d); +DEFINE_EXPECT(testobj_withprop_i); DEFINE_EXPECT(testobj_noprop_d); DEFINE_EXPECT(testobj_onlydispid_d); DEFINE_EXPECT(testobj_onlydispid_i); @@ -124,6 +126,7 @@ DEFINE_EXPECT(DeleteMemberByDispID); #define DISPID_TESTOBJ_PROP 0x2000 #define DISPID_TESTOBJ_ONLYDISPID 0x2001 +#define DISPID_TESTOBJ_WITHPROP 0x2002 #define JS_E_INVALID_CHAR 0x800a03f6 @@ -297,6 +300,12 @@ static HRESULT WINAPI testObj_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD *pid = DISPID_TESTOBJ_PROP; return S_OK; } + if(!strcmp_wa(bstrName, "withProp")) { + CHECK_EXPECT(testobj_withprop_d); + test_grfdex(grfdex, fdexNameCaseSensitive|fdexNameImplicit); + *pid = DISPID_TESTOBJ_WITHPROP; + return S_OK; + } if(!strcmp_wa(bstrName, "noprop")) { CHECK_EXPECT(testobj_noprop_d); test_grfdex(grfdex, fdexNameCaseSensitive); @@ -360,6 +369,23 @@ static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); ok(pei != NULL, "pei == NULL\n"); return DISP_E_MEMBERNOTFOUND; + case DISPID_TESTOBJ_WITHPROP: + CHECK_EXPECT(testobj_withprop_i); + + ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgvarg, "rgvarg != NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_I4; + V_I4(pvarRes) = 1; + + return S_OK; } ok(0, "unexpected call %x\n", id); @@ -1754,6 +1780,12 @@ static BOOL run_tests(void) "});"); CHECK_CALLED(global_testargtypes_i); + SET_EXPECT(testobj_withprop_d); + SET_EXPECT(testobj_withprop_i); + parse_script_a("var t = (function () { with(testObj) { return withProp; }})(); ok(t === 1, 't = ' + t);"); + CHECK_CALLED(testobj_withprop_d); + CHECK_CALLED(testobj_withprop_i); + run_from_res("lang.js"); run_from_res("api.js"); run_from_res("regexp.js");