Module: wine Branch: master Commit: 29d9659095fd76e303f204050ab4c85d0a0486e4 URL: https://source.winehq.org/git/wine.git/?a=commit;h=29d9659095fd76e303f204050...
Author: Jacek Caban jacek@codeweavers.com Date: Wed Mar 31 20:05:26 2021 +0200
jscript: Support calling properties with getters.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/jscript/dispex.c | 130 ++++++++++++++++++++++++++--------------------- dlls/mshtml/tests/es5.js | 13 +++++ 2 files changed, 85 insertions(+), 58 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index a1a1af5a141..973ea4c7142 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -389,64 +389,6 @@ static HRESULT convert_params(const DISPPARAMS *dp, jsval_t *buf, unsigned *argc return S_OK; }
-static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t *prop, WORD flags, - unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) -{ - HRESULT hres; - - switch(prop->type) { - case PROP_BUILTIN: { - if(flags == DISPATCH_CONSTRUCT && (prop->flags & PROPF_METHOD)) { - WARN("%s is not a constructor\n", debugstr_w(prop->name)); - return E_INVALIDARG; - } - - if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) { - vdisp_t vthis; - - if(This->builtin_info->class != JSCLASS_FUNCTION && prop->u.p->invoke != JSGlobal_eval) - flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; - if(jsthis) - set_disp(&vthis, jsthis); - else - set_jsdisp(&vthis, This); - hres = prop->u.p->invoke(This->ctx, &vthis, flags, argc, argv, r); - vdisp_release(&vthis); - }else { - /* Function object calls are special case */ - hres = Function_invoke(This, jsthis, flags, argc, argv, r); - } - return hres; - } - case PROP_PROTREF: - return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, - This->prototype->props+prop->u.ref, flags, argc, argv, r, caller); - case PROP_JSVAL: { - if(!is_object_instance(prop->u.val)) { - FIXME("invoke %s\n", debugstr_jsval(prop->u.val)); - return E_FAIL; - } - - TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val)); - - return disp_call_value(This->ctx, get_object(prop->u.val), - jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface, - flags, argc, argv, r); - } - case PROP_ACCESSOR: - FIXME("accessor\n"); - return E_NOTIMPL; - case PROP_IDX: - FIXME("Invoking PROP_IDX not yet supported\n"); - return E_NOTIMPL; - case PROP_DELETED: - assert(0); - } - - assert(0); - return E_FAIL; -} - static HRESULT prop_get(jsdisp_t *This, dispex_prop_t *prop, jsval_t *r) { jsdisp_t *prop_obj = This; @@ -571,6 +513,78 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val) return S_OK; }
+static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t *prop, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) +{ + HRESULT hres; + + switch(prop->type) { + case PROP_BUILTIN: { + if(flags == DISPATCH_CONSTRUCT && (prop->flags & PROPF_METHOD)) { + WARN("%s is not a constructor\n", debugstr_w(prop->name)); + return E_INVALIDARG; + } + + if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) { + vdisp_t vthis; + + if(This->builtin_info->class != JSCLASS_FUNCTION && prop->u.p->invoke != JSGlobal_eval) + flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; + if(jsthis) + set_disp(&vthis, jsthis); + else + set_jsdisp(&vthis, This); + hres = prop->u.p->invoke(This->ctx, &vthis, flags, argc, argv, r); + vdisp_release(&vthis); + }else { + /* Function object calls are special case */ + hres = Function_invoke(This, jsthis, flags, argc, argv, r); + } + return hres; + } + case PROP_PROTREF: + return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, + This->prototype->props+prop->u.ref, flags, argc, argv, r, caller); + case PROP_JSVAL: { + if(!is_object_instance(prop->u.val) || !get_object(prop->u.val)) { + FIXME("invoke %s\n", debugstr_jsval(prop->u.val)); + return E_FAIL; + } + + TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val)); + + return disp_call_value(This->ctx, get_object(prop->u.val), + jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface, + flags, argc, argv, r); + } + case PROP_ACCESSOR: + case PROP_IDX: { + jsval_t val; + + hres = prop_get(This, prop, &val); + if(FAILED(hres)) + return hres; + + if(is_object_instance(val) && get_object(val)) { + hres = disp_call_value(This->ctx, get_object(val), + jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface, + flags, argc, argv, r); + }else { + FIXME("invoke %s\n", debugstr_jsval(val)); + hres = E_NOTIMPL; + } + + jsval_release(val); + return hres; + } + case PROP_DELETED: + assert(0); + break; + } + + return E_FAIL; +} + HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) { TRACE("%p %s\n", jsthis, debugstr_jsval(value)); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 09ea9e0d657..e8c523b0bf7 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -513,6 +513,19 @@ sync_test("defineProperty", function() { test_accessor_prop_desc(obj, "no_setter", desc); obj.no_setter = false; ok(obj.no_setter === true, "no_setter = " + obj.no_setter); + + /* call prop with getter */ + desc = { + get: function() { + return function(x) { + ok(x === 100, "x = " + x); + return 10; + }; + } + }; + Object.defineProperty(obj, "funcprop", desc); + test_accessor_prop_desc(obj, "funcprop", desc); + ok(obj.funcprop(100) === 10, "obj.funcprop() = " + obj.funcprop(100)); });
sync_test("defineProperties", function() {