Jacek Caban : jscript: Support calling properties with getters.
Alexandre Julliard
julliard at winehq.org
Wed Mar 31 15:55:15 CDT 2021
Module: wine
Branch: master
Commit: 29d9659095fd76e303f204050ab4c85d0a0486e4
URL: https://source.winehq.org/git/wine.git/?a=commit;h=29d9659095fd76e303f204050ab4c85d0a0486e4
Author: Jacek Caban <jacek at codeweavers.com>
Date: Wed Mar 31 20:05:26 2021 +0200
jscript: Support calling properties with getters.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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() {
More information about the wine-cvs
mailing list