diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 270e17299cf..f27965500e6 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -837,3 +837,38 @@ HRESULT disp_call(IDispatch *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS return hres; } + +HRESULT disp_propget(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller) +{ + DISPPARAMS dp = {NULL,NULL,0,0}; + IDispatchEx *dispex; + DispatchEx *jsdisp; + HRESULT hres; + + jsdisp = iface_to_jsdisp((IUnknown*)disp); + if(jsdisp) { + dispex_prop_t *prop; + + prop = get_prop(jsdisp, id); + if(prop) + hres = prop_get(jsdisp, prop, lcid, &dp, val, ei, caller); + else + hres = DISP_E_MEMBERNOTFOUND; + + IDispatchEx_Release(_IDispatchEx_(jsdisp)); + return hres; + } + + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if(FAILED(hres)) { + ULONG err = 0; + + TRACE("uding IDispatch\n"); + return IDispatchEx_Invoke(dispex, id, &IID_NULL, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err); + } + + hres = IDispatchEx_InvokeEx(dispex, id, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, caller); + IDispatchEx_Release(dispex); + + return hres; +} diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index ef66c9767a1..72f723d4ca6 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -23,11 +23,69 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); +#define EXPR_NOVAL 0x0001 +#define EXPR_NEWREF 0x0002 +#define EXPR_STRREF 0x0004 + static inline HRESULT stat_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) { return stat->eval(ctx, stat, rt, ret); } +static inline HRESULT expr_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +{ + return _expr->eval(ctx, _expr, flags, ei, ret); +} + +static void exprval_release(exprval_t *val) +{ + switch(val->type) { + case EXPRVAL_VARIANT: + VariantClear(&val->u.var); + return; + case EXPRVAL_IDREF: + if(val->u.idref.disp) + IDispatch_Release(val->u.idref.disp); + return; + case EXPRVAL_NAMEREF: + if(val->u.nameref.disp) + IDispatch_Release(val->u.nameref.disp); + SysFreeString(val->u.nameref.name); + } +} + +/* ECMA-262 3rd Edition 8.7.1 */ +static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret) +{ + V_VT(ret) = VT_EMPTY; + + switch(val->type) { + case EXPRVAL_VARIANT: + return VariantCopy(ret, &val->u.var); + case EXPRVAL_IDREF: + if(!val->u.idref.disp) { + FIXME("throw ReferenceError\n"); + return E_FAIL; + } + + return disp_propget(val->u.idref.disp, val->u.idref.id, ctx->lcid, ret, ei, NULL/*FIXME*/); + default: + ERR("type %d\n", val->type); + return E_FAIL; + } +} + +static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret) +{ + if(val->type == EXPRVAL_VARIANT) { + *ret = val->u.var; + V_VT(&val->u.var) = VT_EMPTY; + return S_OK; + } + + return exprval_value(ctx, val, ei, ret); +} + HRESULT create_exec_ctx(exec_ctx_t **ret) { exec_ctx_t *ctx; @@ -112,6 +170,7 @@ HRESULT var_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt return E_NOTIMPL; } +/* ECMA-262 3rd Edition 12.3 */ HRESULT empty_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) { TRACE("\n"); @@ -120,10 +179,28 @@ HRESULT empty_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t * return S_OK; } -HRESULT expression_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) +/* ECMA-262 3rd Edition 12.4 */ +HRESULT expression_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) { - FIXME("\n"); - return E_NOTIMPL; + expression_statement_t *stat = (expression_statement_t*)_stat; + exprval_t exprval; + VARIANT val; + HRESULT hres; + + TRACE("\n"); + + hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval); + if(FAILED(hres)) + return hres; + + hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val); + exprval_release(&exprval); + if(FAILED(hres)) + return hres; + + *ret = val; + TRACE("= %s\n", debugstr_variant(ret)); + return S_OK; } HRESULT if_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 6e91178b431..c8dcfba9d7f 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -215,7 +215,24 @@ HRESULT switch_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT throw_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT try_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -typedef struct exprval_t exprval_t; +typedef struct { + enum { + EXPRVAL_VARIANT, + EXPRVAL_IDREF, + EXPRVAL_NAMEREF + } type; + union { + VARIANT var; + struct { + IDispatch *disp; + DISPID id; + } idref; + struct { + IDispatch *disp; + BSTR name; + } nameref; + } u; +} exprval_t; typedef HRESULT (*expression_eval_t)(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index b6761985060..a8cfad27ff7 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -87,6 +87,7 @@ struct DispatchEx { HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,DispatchEx*,DispatchEx**); HRESULT disp_call(IDispatch*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); +HRESULT disp_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); struct _script_ctx_t { LONG ref;