diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 3ea1ed14536..674a61eb7a0 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -23,6 +23,25 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); +typedef enum { + PROP_VARIANT, + PROP_BUILTIN, + PROP_PROTREF, + PROP_DELETED +} prop_type_t; + +struct _dispex_prop_t { + WCHAR *name; + prop_type_t type; + DWORD flags; + + union { + VARIANT var; + const builtin_prop_t *p; + DWORD ref; + } u; +}; + #define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface) static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) @@ -66,8 +85,20 @@ static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) TRACE("(%p) ref=%d\n", This, ref); if(!ref) { + dispex_prop_t *prop; + + for(prop = This->props; prop < This->props+This->prop_cnt; prop++) { + if(prop->type == PROP_VARIANT) + VariantClear(&prop->u.var); + heap_free(prop->name); + } + heap_free(This->props); script_release(This->ctx); - heap_free(This); + + if(This->builtin_info->destructor) + This->builtin_info->destructor(This); + else + heap_free(This); } return ref; @@ -201,10 +232,64 @@ static IDispatchExVtbl DispatchExVtbl = { DispatchEx_GetNameSpaceParent }; -static HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx) +static HRESULT jsdisp_set_prot_prop(DispatchEx *dispex, DispatchEx *prototype) { + VARIANT *var; + + if(!dispex->props[1].name) + return E_OUTOFMEMORY; + + dispex->props[1].type = PROP_VARIANT; + dispex->props[1].flags = 0; + + var = &dispex->props[1].u.var; + V_VT(var) = VT_DISPATCH; + V_DISPATCH(var) = (IDispatch*)_IDispatchEx_(prototype); + + return S_OK; +} + +static HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype) +{ + static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0}; + + TRACE("%p (%p)\n", dispex, prototype); + dispex->lpIDispatchExVtbl = &DispatchExVtbl; dispex->ref = 1; + dispex->builtin_info = builtin_info; + + dispex->props = heap_alloc((dispex->buf_size=4) * sizeof(dispex_prop_t)); + if(!dispex->props) + return E_OUTOFMEMORY; + + dispex->prototype = prototype; + if(prototype) + IDispatchEx_AddRef(_IDispatchEx_(prototype)); + + dispex->prop_cnt = 2; + dispex->props[0].name = NULL; + dispex->props[0].flags = 0; + if(builtin_info->value_prop.invoke) { + dispex->props[0].type = PROP_BUILTIN; + dispex->props[0].u.p = &builtin_info->value_prop; + }else { + dispex->props[0].type = PROP_DELETED; + } + + dispex->props[1].type = PROP_DELETED; + dispex->props[1].name = SysAllocString(prototypeW); + dispex->props[1].flags = 0; + + if(prototype) { + HRESULT hres; + + hres = jsdisp_set_prot_prop(dispex, prototype); + if(FAILED(hres)) { + IDispatchEx_Release(_IDispatchEx_(dispex)); + return hres; + } + } script_addref(ctx); dispex->ctx = ctx; @@ -212,7 +297,15 @@ static HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx) return S_OK; } -HRESULT create_dispex(script_ctx_t *ctx, DispatchEx **dispex) +static const builtin_info_t dispex_info = { + JSCLASS_NONE, + {NULL, NULL, 0}, + 0, NULL, + NULL, + NULL +}; + +HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype, DispatchEx **dispex) { DispatchEx *ret; HRESULT hres; @@ -221,7 +314,7 @@ HRESULT create_dispex(script_ctx_t *ctx, DispatchEx **dispex) if(!ret) return E_OUTOFMEMORY; - hres = init_dispex(ret, ctx); + hres = init_dispex(ret, ctx, builtin_info ? builtin_info : &dispex_info, prototype); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 2bd9f12f40a..f8b95c561f5 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -216,7 +216,7 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface, return hres; } - hres = create_dispex(This->ctx, &This->ctx->script_disp); + hres = create_dispex(This->ctx, NULL, NULL, &This->ctx->script_disp); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 0fff0e89bab..b4c872eec2a 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -33,23 +33,59 @@ typedef struct _script_ctx_t script_ctx_t; typedef struct _exec_ctx_t exec_ctx_t; +typedef struct _dispex_prop_t dispex_prop_t; typedef struct { EXCEPINFO ei; VARIANT var; } jsexcept_t; -typedef struct DispatchEx { +typedef struct DispatchEx DispatchEx; + +#define PROPF_ARGMASK 0x00ff +#define PROPF_METHOD 0x0100 +#define PROPF_ENUM 0x0200 +#define PROPF_CONSTR 0x0400 + +typedef enum { + JSCLASS_NONE +} jsclass_t; + +typedef HRESULT (*builtin_invoke_t)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); + +typedef struct { + const WCHAR *name; + builtin_invoke_t invoke; + DWORD flags; +} builtin_prop_t; + +typedef struct { + jsclass_t class; + builtin_prop_t value_prop; + DWORD props_cnt; + const builtin_prop_t *props; + void (*destructor)(DispatchEx*); + void (*on_put)(DispatchEx*,const WCHAR*); +} builtin_info_t; + +struct DispatchEx { const IDispatchExVtbl *lpIDispatchExVtbl; LONG ref; + DWORD buf_size; + DWORD prop_cnt; + dispex_prop_t *props; script_ctx_t *ctx; -} DispatchEx; + + DispatchEx *prototype; + + const builtin_info_t *builtin_info; +}; #define _IDispatchEx_(x) ((IDispatchEx*) &(x)->lpIDispatchExVtbl) -HRESULT create_dispex(script_ctx_t*,DispatchEx**); +HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,DispatchEx*,DispatchEx**); struct _script_ctx_t { LONG ref;