From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 175 +++++++++++++++++++++++++---------------- dlls/jscript/jscript.h | 15 ++++ 2 files changed, 124 insertions(+), 66 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 57882bf499e..5f41443f83d 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -60,6 +60,13 @@ struct _dispex_prop_t { int bucket_next; };
+static const struct prop_desc_vtbl dispex_prop_vtbl; + +static inline DWORD prop_id_to_idx(DISPID id) +{ + return id - 1; +} + static void fix_protref_prop(jsdisp_t *jsdisp, dispex_prop_t *prop) { DWORD ref; @@ -84,15 +91,21 @@ static inline DISPID prop_to_id(jsdisp_t *This, dispex_prop_t *prop) return prop - This->props + 1; }
-static inline dispex_prop_t *get_prop(jsdisp_t *This, DISPID id) +static inline BOOL get_prop(jsdisp_t *This, DISPID id, struct prop_desc *ret) { - DWORD idx = id - 1; + DWORD idx = prop_id_to_idx(id);
if(idx >= This->prop_cnt) - return NULL; + return FALSE; fix_protref_prop(This, &This->props[idx]);
- return This->props[idx].type == PROP_DELETED ? NULL : &This->props[idx]; + if(This->props[idx].type == PROP_DELETED) + return FALSE; + + ret->vtbl = &dispex_prop_vtbl; + ret->jsdisp = This; + ret->id = id; + return TRUE; }
static inline BOOL is_function_prop(dispex_prop_t *prop) @@ -603,6 +616,69 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t return E_FAIL; }
+static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) +{ + if(prop->type == PROP_PROTREF) { + *ret = TRUE; + return S_OK; + } + + if(!(prop->flags & PROPF_CONFIGURABLE)) { + *ret = FALSE; + return S_OK; + } + + *ret = TRUE; + + if(prop->type == PROP_JSVAL) + jsval_release(prop->u.val); + if(prop->type == PROP_ACCESSOR) { + if(prop->u.accessor.getter) + jsdisp_release(prop->u.accessor.getter); + if(prop->u.accessor.setter) + jsdisp_release(prop->u.accessor.setter); + } + prop->type = PROP_DELETED; + return S_OK; +} + +static HRESULT dispex_prop_get(struct prop_desc *prop, IDispatch *jsthis, jsval_t *r) +{ + return prop_get(prop->jsdisp, jsthis, &prop->jsdisp->props[prop_id_to_idx(prop->id)], r); +} + +static HRESULT dispex_prop_put(struct prop_desc *prop, jsval_t val) +{ + return prop_put(prop->jsdisp, &prop->jsdisp->props[prop_id_to_idx(prop->id)], val); +} + +static HRESULT dispex_prop_invoke(struct prop_desc *prop, IDispatch *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) +{ + return invoke_prop_func(prop->jsdisp, jsthis, &prop->jsdisp->props[prop_id_to_idx(prop->id)], flags, argc, argv, r, caller); +} + +static HRESULT dispex_prop_delete(struct prop_desc *prop, BOOL *ret) +{ + return delete_prop(&prop->jsdisp->props[prop_id_to_idx(prop->id)], ret); +} + +static void *dispex_prop_get_name(struct prop_desc *prop, BOOL bstr) +{ + const WCHAR *name = prop->jsdisp->props[prop_id_to_idx(prop->id)].name; + if(bstr) + return SysAllocString(name); + return jsstr_alloc(name); +} + +static const struct prop_desc_vtbl dispex_prop_vtbl = { + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name +}; + HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) { TRACE("%p %s\n", jsthis, debugstr_jsval(value)); @@ -1916,7 +1992,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc { jsdisp_t *This = impl_from_IDispatchEx(iface); IServiceProvider *prev_caller; - dispex_prop_t *prop; + struct prop_desc prop; jsexcept_t ei; HRESULT hres;
@@ -1925,8 +2001,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if(pvarRes) V_VT(pvarRes) = VT_EMPTY;
- prop = get_prop(This, id); - if(!prop && id != DISPID_VALUE) { + if(!get_prop(This, id, &prop) && id != DISPID_VALUE) { TRACE("invalid id\n"); return DISP_E_MEMBERNOTFOUND; } @@ -1953,8 +2028,8 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc break;
passed_this = get_this(pdp); - if(prop) - hres = invoke_prop_func(This, passed_this, prop, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller); + if(id != DISPID_VALUE) + hres = prop.vtbl->invoke(&prop, passed_this, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller); else hres = jsdisp_call_value(This, passed_this ? jsval_disp(passed_this) : jsval_undefined(), wFlags, argc, argv, pvarRes ? &r : NULL);
@@ -1971,8 +2046,8 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc case DISPATCH_PROPERTYGET: { jsval_t r;
- if(prop) - hres = prop_get(This, to_disp(This), prop, &r); + if(id != DISPID_VALUE) + hres = prop.vtbl->get(&prop, to_disp(This), &r); else { hres = to_primitive(This->ctx, jsval_obj(This), &r, NO_HINT); if(hres == JS_E_TO_PRIMITIVE) @@ -1991,7 +2066,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc jsval_t val; DWORD i;
- if(!prop) { + if(id == DISPID_VALUE) { hres = DISP_E_MEMBERNOTFOUND; break; } @@ -2011,7 +2086,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if(FAILED(hres)) break;
- hres = prop_put(This, prop, val); + prop.vtbl->put(&prop, val); jsval_release(val); break; } @@ -2027,32 +2102,6 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc return leave_script(This->ctx, hres); }
-static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) -{ - if(prop->type == PROP_PROTREF) { - *ret = TRUE; - return S_OK; - } - - if(!(prop->flags & PROPF_CONFIGURABLE)) { - *ret = FALSE; - return S_OK; - } - - *ret = TRUE; - - if(prop->type == PROP_JSVAL) - jsval_release(prop->u.val); - if(prop->type == PROP_ACCESSOR) { - if(prop->u.accessor.getter) - jsdisp_release(prop->u.accessor.getter); - if(prop->u.accessor.setter) - jsdisp_release(prop->u.accessor.setter); - } - prop->type = PROP_DELETED; - return S_OK; -} - static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) { jsdisp_t *This = impl_from_IDispatchEx(iface); @@ -2079,18 +2128,17 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bst static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) { jsdisp_t *This = impl_from_IDispatchEx(iface); - dispex_prop_t *prop; + struct prop_desc prop; BOOL b;
TRACE("(%p)->(%lx)\n", This, id);
- prop = get_prop(This, id); - if(!prop) { + if(!get_prop(This, id, &prop)) { WARN("invalid id\n"); return DISP_E_MEMBERNOTFOUND; }
- return delete_prop(prop, &b); + return prop.vtbl->delete(&prop, &b); }
static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) @@ -2103,15 +2151,14 @@ static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) { jsdisp_t *This = impl_from_IDispatchEx(iface); - dispex_prop_t *prop; + struct prop_desc prop;
TRACE("(%p)->(%lx %p)\n", This, id, pbstrName);
- prop = get_prop(This, id); - if(!prop) + if(!get_prop(This, id, &prop)) return DISP_E_MEMBERNOTFOUND;
- *pbstrName = SysAllocString(prop->name); + *pbstrName = prop.vtbl->get_name(&prop, TRUE); if(!*pbstrName) return E_OUTOFMEMORY;
@@ -2388,13 +2435,12 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, jsval_t vthis, WORD flags, unsigned
HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - dispex_prop_t *prop; + struct prop_desc prop;
- prop = get_prop(disp, id); - if(!prop) + if(!get_prop(disp, id, &prop)) return DISP_E_MEMBERNOTFOUND;
- return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface); + return prop.vtbl->invoke(&prop, to_disp(disp), flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface); }
HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) @@ -2672,11 +2718,10 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val)
jsdisp = iface_to_jsdisp(disp); if(jsdisp && jsdisp->ctx == ctx) { - dispex_prop_t *prop; + struct prop_desc prop;
- prop = get_prop(jsdisp, id); - if(prop) - hres = prop_put(jsdisp, prop, val); + if(get_prop(jsdisp, id, &prop)) + hres = prop.vtbl->put(&prop, val); else hres = DISP_E_MEMBERNOTFOUND;
@@ -2778,13 +2823,12 @@ HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r)
HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val) { - dispex_prop_t *prop; + struct prop_desc prop;
- prop = get_prop(jsdisp, id); - if(!prop) + if(!get_prop(jsdisp, id, &prop)) return DISP_E_MEMBERNOTFOUND;
- return prop_get(jsdisp, to_disp(jsdisp), prop, val); + return prop.vtbl->get(&prop, to_disp(jsdisp), val); }
HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val) @@ -2839,11 +2883,10 @@ HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret)
jsdisp = iface_to_jsdisp(disp); if(jsdisp) { - dispex_prop_t *prop; + struct prop_desc prop;
- prop = get_prop(jsdisp, id); - if(prop) - hres = delete_prop(prop, ret); + if(get_prop(jsdisp, id, &prop)) + hres = prop.vtbl->delete(&prop, ret); else hres = DISP_E_MEMBERNOTFOUND;
@@ -3199,11 +3242,11 @@ BOOL jsdisp_is_frozen(jsdisp_t *obj, BOOL sealed)
HRESULT jsdisp_get_prop_name(jsdisp_t *obj, DISPID id, jsstr_t **r) { - dispex_prop_t *prop = get_prop(obj, id); + struct prop_desc prop;
- if(!prop) + if(!get_prop(obj, id, &prop)) return DISP_E_MEMBERNOTFOUND;
- *r = jsstr_alloc(prop->name); + *r = prop.vtbl->get_name(&prop, FALSE); return *r ? S_OK : E_OUTOFMEMORY; } diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 1a9446893a1..06be65fd153 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -53,6 +53,7 @@ typedef struct _jsexcept_t jsexcept_t; typedef struct _script_ctx_t script_ctx_t; typedef struct _dispex_prop_t dispex_prop_t; typedef struct _property_desc_t property_desc_t; +struct prop_desc_vtbl;
typedef struct { void **blocks; @@ -247,6 +248,20 @@ void jsdisp_release(jsdisp_t*);
#endif
+struct prop_desc { + const struct prop_desc_vtbl *vtbl; + jsdisp_t *jsdisp; + DISPID id; +}; + +struct prop_desc_vtbl { + HRESULT (*get)(struct prop_desc*,IDispatch*,jsval_t*); + HRESULT (*put)(struct prop_desc*,jsval_t); + HRESULT (*invoke)(struct prop_desc*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*); + HRESULT (*delete)(struct prop_desc*,BOOL*); + void *(*get_name)(struct prop_desc*,BOOL); +}; + enum jsdisp_enum_type { JSDISP_ENUM_ALL, JSDISP_ENUM_OWN,