This MR adds a very minimal support for new MSHTML objects bindings that will ultimately allow implementing IE9+ behavior. The plan is to have something testable that we can increment on. It's enabled only for the `Screen` object for now (which is an example of an object without custom properties with no functions). The next step is to work incrementally on enabling it for all MSHTML objects.
A few comments on the approach:
- The object and its jscript representation share reference counter. This may not be optimal, but it essentially preserves the current behavior where MSHTML is responsible for tracking it. I expect that we will want to revisit that when integrating cycle collector with jscript. - Deleting properties is not yet supported; this will need another function in the interface, but it's not yet needed as we currently don't allow deleting builtin properties anyway (and custom properties are skipped in this MR as they are not needed for the `Screen` object). - Functions are not yet supported, only old-style properties (not accessor properties yet). They are straightforward to support on top of it by extending `property_info` struct to pass iid and implementing them as jscript function. - This does not yet allow host properties to appear and disappear without notifications. This is a limitation of jscript's `dispex.c` (not the interface), which will need to be tweaked before we use new bindings for objects that require it.
-- v2: mshtml: Use IWineJSDispatch for screen object script bindings. mshtml: Support using IWineJSDispatch for DispatchEx implementation. mshtml: Pass an optional script global window to init_dispatch. mshtml: Implement jscript IWineJSDispatchHost. jscript: Use jsdisp_t internally for host objects that support it. jscript: Support host objects in disp_cmp. jscript: Support converting host objects to string.
From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 138 +++++++++++++++++++++-------------------- dlls/jscript/jscript.h | 29 +-------- 2 files changed, 74 insertions(+), 93 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 8813f6bb71a..440cfc6aaac 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -877,6 +877,11 @@ HRESULT gc_run(script_ctx_t *ctx) chunk->ref[chunk_idx++] = obj->ref; } LIST_FOR_EACH_ENTRY(obj, &thread_data->objects, jsdisp_t, entry) { + /* Skip objects with external reference counter */ + if(obj->builtin_info->addref) { + obj->gc_marked = FALSE; + continue; + } for(prop = obj->props, props_end = prop + obj->prop_cnt; prop < props_end; prop++) { switch(prop->type) { case PROP_JSVAL: @@ -1763,6 +1768,69 @@ static const ITypeCompVtbl ScriptTypeCompVtbl = { ScriptTypeComp_BindType };
+static void jsdisp_free(jsdisp_t *obj) +{ + dispex_prop_t *prop; + + list_remove(&obj->entry); + + TRACE("(%p)\n", obj); + + if(obj->has_weak_refs) { + struct list *list = &RB_ENTRY_VALUE(rb_get(&obj->ctx->thread_data->weak_refs, obj), struct weak_refs_entry, entry)->list; + do { + remove_weakmap_entry(LIST_ENTRY(list->next, struct weakmap_entry, weak_refs_entry)); + } while(obj->has_weak_refs); + } + + for(prop = obj->props; prop < obj->props+obj->prop_cnt; prop++) { + switch(prop->type) { + case PROP_JSVAL: + jsval_release(prop->u.val); + break; + case PROP_ACCESSOR: + if(prop->u.accessor.getter) + jsdisp_release(prop->u.accessor.getter); + if(prop->u.accessor.setter) + jsdisp_release(prop->u.accessor.setter); + break; + default: + break; + }; + free(prop->name); + } + free(obj->props); + script_release(obj->ctx); + if(obj->prototype) + jsdisp_release(obj->prototype); + + if(obj->builtin_info->destructor) + obj->builtin_info->destructor(obj); + free(obj); +} + +jsdisp_t *jsdisp_addref(jsdisp_t *obj) +{ + if(obj->builtin_info->addref) + obj->builtin_info->addref(obj); + else + ++obj->ref; + return obj; +} + +ULONG jsdisp_release(jsdisp_t *obj) +{ + ULONG ref; + + if(obj->builtin_info->release) + return obj->builtin_info->release(obj); + + ref = --obj->ref; + if(!ref) + jsdisp_free(obj); + return ref; +} + static inline jsdisp_t *impl_from_IDispatchEx(IDispatchEx *iface) { return CONTAINING_RECORD(iface, jsdisp_t, IDispatchEx_iface); @@ -1794,6 +1862,8 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) { jsdisp_t *This = impl_from_IDispatchEx(iface); + if(This->builtin_info->addref) + return This->builtin_info->addref(This); jsdisp_addref(This); return This->ref; } @@ -1801,11 +1871,7 @@ static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) { jsdisp_t *This = impl_from_IDispatchEx(iface); - ULONG ref = --This->ref; - TRACE("(%p) ref=%ld\n", This, ref); - if(!ref) - jsdisp_free(This); - return ref; + return jsdisp_release(This); }
static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) @@ -2285,68 +2351,6 @@ HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, jsd return S_OK; }
-void jsdisp_free(jsdisp_t *obj) -{ - dispex_prop_t *prop; - - list_remove(&obj->entry); - - TRACE("(%p)\n", obj); - - if(obj->has_weak_refs) { - struct list *list = &RB_ENTRY_VALUE(rb_get(&obj->ctx->thread_data->weak_refs, obj), struct weak_refs_entry, entry)->list; - do { - remove_weakmap_entry(LIST_ENTRY(list->next, struct weakmap_entry, weak_refs_entry)); - } while(obj->has_weak_refs); - } - - for(prop = obj->props; prop < obj->props+obj->prop_cnt; prop++) { - switch(prop->type) { - case PROP_JSVAL: - jsval_release(prop->u.val); - break; - case PROP_ACCESSOR: - if(prop->u.accessor.getter) - jsdisp_release(prop->u.accessor.getter); - if(prop->u.accessor.setter) - jsdisp_release(prop->u.accessor.setter); - break; - default: - break; - }; - free(prop->name); - } - free(obj->props); - script_release(obj->ctx); - if(obj->prototype) - jsdisp_release(obj->prototype); - - if(obj->builtin_info->destructor) - obj->builtin_info->destructor(obj); - free(obj); -} - -#ifdef TRACE_REFCNT - -jsdisp_t *jsdisp_addref(jsdisp_t *jsdisp) -{ - ULONG ref = ++jsdisp->ref; - TRACE("(%p) ref=%ld\n", jsdisp, ref); - return jsdisp; -} - -void jsdisp_release(jsdisp_t *jsdisp) -{ - ULONG ref = --jsdisp->ref; - - TRACE("(%p) ref=%ld\n", jsdisp, ref); - - if(!ref) - jsdisp_free(jsdisp); -} - -#endif - HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *constr) { jsdisp_t *prot = NULL; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index e091e7acd90..b6248ac6e39 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -190,6 +190,8 @@ typedef struct { DWORD props_cnt; const builtin_prop_t *props; void (*destructor)(jsdisp_t*); + ULONG (*addref)(jsdisp_t*); + ULONG (*release)(jsdisp_t*); void (*on_put)(jsdisp_t*,const WCHAR*); HRESULT (*lookup_prop)(jsdisp_t*,const WCHAR*,struct property_info*); HRESULT (*next_prop)(jsdisp_t*,unsigned,struct property_info*); @@ -230,34 +232,9 @@ static inline IDispatchEx *to_dispex(jsdisp_t *jsdisp)
jsdisp_t *as_jsdisp(IDispatch*); jsdisp_t *to_jsdisp(IDispatch*); -void jsdisp_free(jsdisp_t*); - -#ifndef TRACE_REFCNT - -/* - * We do a lot of refcount calls during script execution, so having an inline - * version is a nice perf win. Define TRACE_REFCNT macro when debugging - * refcount bugs to have traces. Also, since jsdisp_t is not thread safe anyways, - * there is no point in using atomic operations. - */ -static inline jsdisp_t *jsdisp_addref(jsdisp_t *jsdisp) -{ - jsdisp->ref++; - return jsdisp; -} - -static inline void jsdisp_release(jsdisp_t *jsdisp) -{ - if(!--jsdisp->ref) - jsdisp_free(jsdisp); -} - -#else
jsdisp_t *jsdisp_addref(jsdisp_t*); -void jsdisp_release(jsdisp_t*); - -#endif +ULONG jsdisp_release(jsdisp_t*);
enum jsdisp_enum_type { JSDISP_ENUM_ALL,
From: Jacek Caban jacek@codeweavers.com
Based on patch by Gabriel Ivăncescu. --- dlls/jscript/Makefile.in | 1 + dlls/jscript/dispex.c | 94 ++++++++++++++++++++++------------------ dlls/jscript/jscript.h | 16 ++----- dlls/jscript/jsdisp.idl | 42 ++++++++++++++++++ 4 files changed, 100 insertions(+), 53 deletions(-) create mode 100644 dlls/jscript/jsdisp.idl
diff --git a/dlls/jscript/Makefile.in b/dlls/jscript/Makefile.in index 86d9035800e..0919cfe9bf0 100644 --- a/dlls/jscript/Makefile.in +++ b/dlls/jscript/Makefile.in @@ -20,6 +20,7 @@ SOURCES = \ jscript.rc \ jscript_classes.idl \ jscript_main.c \ + jsdisp.idl \ jsglobal.idl \ json.c \ jsregexp.c \ diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 440cfc6aaac..895e72e041d 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1831,24 +1831,27 @@ ULONG jsdisp_release(jsdisp_t *obj) return ref; }
-static inline jsdisp_t *impl_from_IDispatchEx(IDispatchEx *iface) +static inline jsdisp_t *impl_from_IWineJSDispatch(IWineJSDispatch *iface) { - return CONTAINING_RECORD(iface, jsdisp_t, IDispatchEx_iface); + return CONTAINING_RECORD(iface, jsdisp_t, IWineJSDispatch_iface); }
-static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +static HRESULT WINAPI DispatchEx_QueryInterface(IWineJSDispatch *iface, REFIID riid, void **ppv) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface);
if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = &This->IDispatchEx_iface; + *ppv = &This->IWineJSDispatch_iface; }else if(IsEqualGUID(&IID_IDispatch, riid)) { TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); - *ppv = &This->IDispatchEx_iface; + *ppv = &This->IWineJSDispatch_iface; }else if(IsEqualGUID(&IID_IDispatchEx, riid)) { TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv); - *ppv = &This->IDispatchEx_iface; + *ppv = &This->IWineJSDispatch_iface; + }else if(IsEqualGUID(&IID_IWineJSDispatch, riid)) { + TRACE("(%p)->(IID_IWineJSDispatch %p)\n", This, ppv); + *ppv = &This->IWineJSDispatch_iface; }else { WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); *ppv = NULL; @@ -1859,24 +1862,24 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, return S_OK; }
-static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) +static ULONG WINAPI DispatchEx_AddRef(IWineJSDispatch *iface) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); if(This->builtin_info->addref) return This->builtin_info->addref(This); jsdisp_addref(This); return This->ref; }
-static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) +static ULONG WINAPI DispatchEx_Release(IWineJSDispatch *iface) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); return jsdisp_release(This); }
-static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) +static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IWineJSDispatch *iface, UINT *pctinfo) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface);
TRACE("(%p)->(%p)\n", This, pctinfo);
@@ -1884,10 +1887,10 @@ static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pcti return S_OK; }
-static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, +static HRESULT WINAPI DispatchEx_GetTypeInfo(IWineJSDispatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); dispex_prop_t *prop, *cur, *end, **typevar; UINT num_funcs = 0, num_vars = 0; struct typeinfo_func *typefunc; @@ -1982,11 +1985,11 @@ static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LC return S_OK; }
-static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, +static HRESULT WINAPI DispatchEx_GetIDsOfNames(IWineJSDispatch *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); UINT i; HRESULT hres;
@@ -2010,11 +2013,11 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, return hres; }
-static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, +static HRESULT WINAPI DispatchEx_Invoke(IWineJSDispatch *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface);
TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); @@ -2023,9 +2026,9 @@ static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, pDispParams, pVarResult, pExcepInfo, NULL); }
-static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +static HRESULT WINAPI DispatchEx_GetDispID(IWineJSDispatch *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface);
TRACE("(%p)->(%s %lx %p)\n", This, debugstr_w(bstrName), grfdex, pid);
@@ -2037,10 +2040,10 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW return jsdisp_get_id(This, bstrName, grfdex, pid); }
-static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, +static HRESULT WINAPI DispatchEx_InvokeEx(IWineJSDispatch *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); IServiceProvider *prev_caller; dispex_prop_t *prop; jsexcept_t ei; @@ -2179,9 +2182,9 @@ static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) return S_OK; }
-static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) +static HRESULT WINAPI DispatchEx_DeleteMemberByName(IWineJSDispatch *iface, BSTR bstrName, DWORD grfdex) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); dispex_prop_t *prop; BOOL b; HRESULT hres; @@ -2202,9 +2205,9 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bst return delete_prop(prop, &b); }
-static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) +static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IWineJSDispatch *iface, DISPID id) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); dispex_prop_t *prop; BOOL b;
@@ -2219,16 +2222,16 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID return delete_prop(prop, &b); }
-static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) +static HRESULT WINAPI DispatchEx_GetMemberProperties(IWineJSDispatch *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); FIXME("(%p)->(%lx %lx %p)\n", This, id, grfdexFetch, pgrfdex); return E_NOTIMPL; }
-static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) +static HRESULT WINAPI DispatchEx_GetMemberName(IWineJSDispatch *iface, DISPID id, BSTR *pbstrName) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); dispex_prop_t *prop;
TRACE("(%p)->(%lx %p)\n", This, id, pbstrName); @@ -2244,9 +2247,9 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BS return S_OK; }
-static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) +static HRESULT WINAPI DispatchEx_GetNextDispID(IWineJSDispatch *iface, DWORD grfdex, DISPID id, DISPID *pid) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); HRESULT hres = S_FALSE;
TRACE("(%p)->(%lx %lx %p)\n", This, grfdex, id, pid); @@ -2258,14 +2261,20 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, return hres; }
-static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) +static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IWineJSDispatch *iface, IUnknown **ppunk) { - jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_t *This = impl_from_IWineJSDispatch(iface); FIXME("(%p)->(%p)\n", This, ppunk); return E_NOTIMPL; }
-static IDispatchExVtbl DispatchExVtbl = { +static void WINAPI WineJSDispatch_Free(IWineJSDispatch *iface) +{ + jsdisp_t *This = impl_from_IWineJSDispatch(iface); + jsdisp_free(This); + } + +static IWineJSDispatchVtbl DispatchExVtbl = { DispatchEx_QueryInterface, DispatchEx_AddRef, DispatchEx_Release, @@ -2280,18 +2289,21 @@ static IDispatchExVtbl DispatchExVtbl = { DispatchEx_GetMemberProperties, DispatchEx_GetMemberName, DispatchEx_GetNextDispID, - DispatchEx_GetNameSpaceParent + DispatchEx_GetNameSpaceParent, + WineJSDispatch_Free, };
jsdisp_t *as_jsdisp(IDispatch *disp) { assert(disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl); - return impl_from_IDispatchEx((IDispatchEx*)disp); + return impl_from_IWineJSDispatch((IWineJSDispatch*)disp); }
jsdisp_t *to_jsdisp(IDispatch *disp) { - return disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl ? impl_from_IDispatchEx((IDispatchEx*)disp) : NULL; + if(disp->lpVtbl != (IDispatchVtbl*)&DispatchExVtbl) + return NULL; + return impl_from_IWineJSDispatch((IWineJSDispatch*)disp); }
HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype) @@ -2304,7 +2316,7 @@ HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *b
TRACE("%p (%p)\n", dispex, prototype);
- dispex->IDispatchEx_iface.lpVtbl = &DispatchExVtbl; + dispex->IWineJSDispatch_iface.lpVtbl = &DispatchExVtbl; dispex->ref = 1; dispex->builtin_info = builtin_info; dispex->extensible = TRUE; @@ -2385,7 +2397,7 @@ HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const built jsdisp_t *iface_to_jsdisp(IDispatch *iface) { return iface->lpVtbl == (const IDispatchVtbl*)&DispatchExVtbl - ? jsdisp_addref( impl_from_IDispatchEx((IDispatchEx*)iface)) + ? jsdisp_addref( impl_from_IWineJSDispatch((IWineJSDispatch*)iface)) : NULL; }
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index b6248ac6e39..3113c0d5a8c 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -28,6 +28,7 @@ #include "ole2.h" #include "dispex.h" #include "activscp.h" +#include "jsdisp.h"
#include "resource.h"
@@ -79,9 +80,6 @@ HRESULT get_dispatch_typeinfo(ITypeInfo**); #define PROPF_METHOD 0x0100 #define PROPF_CONSTR 0x0200
-#define PROPF_ENUMERABLE 0x0400 -#define PROPF_WRITABLE 0x0800 -#define PROPF_CONFIGURABLE 0x1000 #define PROPF_ALL (PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE)
#define PROPF_VERSION_MASK 0x01ff0000 @@ -178,12 +176,6 @@ typedef struct { builtin_setter_t setter; } builtin_prop_t;
-struct property_info -{ - UINT32 id; - UINT32 flags; -}; - typedef struct { jsclass_t class; builtin_invoke_t call; @@ -201,7 +193,7 @@ typedef struct { } builtin_info_t;
struct jsdisp_t { - IDispatchEx IDispatchEx_iface; + IWineJSDispatch IWineJSDispatch_iface;
LONG ref;
@@ -222,12 +214,12 @@ struct jsdisp_t {
static inline IDispatch *to_disp(jsdisp_t *jsdisp) { - return (IDispatch*)&jsdisp->IDispatchEx_iface; + return (IDispatch *)&jsdisp->IWineJSDispatch_iface; }
static inline IDispatchEx *to_dispex(jsdisp_t *jsdisp) { - return &jsdisp->IDispatchEx_iface; + return (IDispatchEx *)&jsdisp->IWineJSDispatch_iface; }
jsdisp_t *as_jsdisp(IDispatch*); diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl new file mode 100644 index 00000000000..b7cb27a585b --- /dev/null +++ b/dlls/jscript/jsdisp.idl @@ -0,0 +1,42 @@ +/* + * Copyright 2024 Gabriel Ivăncescu for CodeWeavers + * Copyright 2024 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep header + +import "dispex.idl"; + +struct property_info +{ + UINT32 id; + UINT32 flags; +}; + +const unsigned int PROPF_ENUMERABLE = 0x0400; +const unsigned int PROPF_WRITABLE = 0x0800; +const unsigned int PROPF_CONFIGURABLE = 0x1000; + +[ + object, + uuid(d359f2fe-5531-741b-a41a-5cf92edc971c), + local +] +interface IWineJSDispatch : IDispatchEx +{ + void Free(); +}
From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 20 ++++++++++++++------ dlls/jscript/engine.c | 2 +- dlls/jscript/function.c | 2 +- dlls/jscript/jscript.h | 2 +- dlls/jscript/jsdisp.idl | 2 ++ dlls/jscript/string.c | 2 +- 6 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 895e72e041d..911b3ab1d73 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -276,12 +276,13 @@ static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_i struct property_info desc; HRESULT hres;
- hres = This->builtin_info->lookup_prop(This, name, &desc); + hres = This->builtin_info->lookup_prop(This, name, + case_insens ? fdexNameCaseInsensitive : fdexNameCaseSensitive, &desc); if(hres != DISP_E_UNKNOWNNAME) { if(FAILED(hres)) return hres;
- prop = alloc_prop(This, name, PROP_EXTERN, desc.flags); + prop = alloc_prop(This, desc.name ? desc.name : name, PROP_EXTERN, desc.flags); if(!prop) return E_OUTOFMEMORY;
@@ -424,6 +425,8 @@ HRESULT jsdisp_index_lookup(jsdisp_t *obj, const WCHAR *name, unsigned length, s desc->flags = PROPF_ENUMERABLE; if(obj->builtin_info->prop_put) desc->flags |= PROPF_WRITABLE; + desc->name = NULL; + desc->index = idx; return S_OK; }
@@ -435,6 +438,8 @@ HRESULT jsdisp_next_index(jsdisp_t *obj, unsigned length, unsigned id, struct pr desc->flags = PROPF_ENUMERABLE; if(obj->builtin_info->prop_put) desc->flags |= PROPF_WRITABLE; + desc->name = NULL; + desc->index = desc->id; return S_OK; }
@@ -664,7 +669,7 @@ static HRESULT fill_props(jsdisp_t *obj) if(obj->builtin_info->next_prop) { struct property_info desc; unsigned id = ~0; - WCHAR name[12]; + WCHAR buf[12];
for(;;) { hres = obj->builtin_info->next_prop(obj, id, &desc); @@ -673,11 +678,14 @@ static HRESULT fill_props(jsdisp_t *obj) if(hres == S_FALSE) break;
- swprintf(name, ARRAYSIZE(name), L"%u", desc.id); + if(!desc.name) { + swprintf(buf, ARRAYSIZE(buf), L"%u", desc.index); + desc.name = buf; + }
- prop = lookup_dispex_prop(obj, string_hash(name), name, FALSE); + prop = lookup_dispex_prop(obj, string_hash(desc.name), desc.name, FALSE); if(!prop) { - prop = alloc_prop(obj, name, PROP_EXTERN, desc.flags); + prop = alloc_prop(obj, desc.name, PROP_EXTERN, desc.flags); if(!prop) return E_OUTOFMEMORY; prop->u.id = desc.id; diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index e84d2f9b2d8..2be22a9b526 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -478,7 +478,7 @@ static void scope_destructor(jsdisp_t *dispex) IDispatch_Release(scope->obj); }
-static HRESULT scope_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct property_info *desc) +static HRESULT scope_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, unsigned flags, struct property_info *desc) { scope_chain_t *scope = scope_from_dispex(jsdisp);
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 654bf12c7e9..27678fc167c 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -117,7 +117,7 @@ static void Arguments_destructor(jsdisp_t *jsdisp) scope_release(arguments->scope); }
-static HRESULT Arguments_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct property_info *desc) +static HRESULT Arguments_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, unsigned flags, struct property_info *desc) { ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); return jsdisp_index_lookup(&arguments->jsdisp, name, arguments->argc, desc); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 3113c0d5a8c..9454d9e3beb 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -185,7 +185,7 @@ typedef struct { ULONG (*addref)(jsdisp_t*); ULONG (*release)(jsdisp_t*); void (*on_put)(jsdisp_t*,const WCHAR*); - HRESULT (*lookup_prop)(jsdisp_t*,const WCHAR*,struct property_info*); + HRESULT (*lookup_prop)(jsdisp_t*,const WCHAR*,unsigned,struct property_info*); HRESULT (*next_prop)(jsdisp_t*,unsigned,struct property_info*); HRESULT (*prop_get)(jsdisp_t*,unsigned,jsval_t*); HRESULT (*prop_put)(jsdisp_t*,unsigned,jsval_t); diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index b7cb27a585b..f053149c144 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -25,6 +25,8 @@ struct property_info { UINT32 id; UINT32 flags; + const WCHAR *name; + UINT32 index; };
const unsigned int PROPF_ENUMERABLE = 0x0400; diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 3cad5c55a79..968b74f9602 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1501,7 +1501,7 @@ static void String_destructor(jsdisp_t *dispex) jsstr_release(This->str); }
-static HRESULT String_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct property_info *desc) +static HRESULT String_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, unsigned flags, struct property_info *desc) { StringInstance *string = string_from_jsdisp(jsdisp);
From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 104 ++++++++++++++++++++++++++++++++++++ dlls/jscript/jscript.c | 42 +++++++++++++++ dlls/jscript/jscript.h | 1 + dlls/jscript/jscript_main.c | 1 + dlls/jscript/jsdisp.idl | 25 +++++++++ 5 files changed, 173 insertions(+)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 911b3ab1d73..b684b9edd99 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -3273,3 +3273,107 @@ HRESULT jsdisp_get_prop_name(jsdisp_t *obj, DISPID id, jsstr_t **r) *r = jsstr_alloc(prop->name); return *r ? S_OK : E_OUTOFMEMORY; } + +typedef struct { + jsdisp_t jsdisp; + IWineJSDispatchHost *host_iface; +} HostObject; + +static inline HostObject *HostObject_from_jsdisp(jsdisp_t *jsdisp) +{ + return CONTAINING_RECORD(jsdisp, HostObject, jsdisp); +} + +static ULONG HostObject_addref(jsdisp_t *jsdisp) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + return IWineJSDispatchHost_AddRef(This->host_iface); +} + +static ULONG HostObject_release(jsdisp_t *jsdisp) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + return IWineJSDispatchHost_Release(This->host_iface); +} + +static HRESULT HostObject_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, unsigned flags, struct property_info *desc) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + + return IWineJSDispatchHost_LookupProperty(This->host_iface, name, flags, desc); +} + +static HRESULT HostObject_prop_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + EXCEPINFO ei = { 0 }; + VARIANT v; + HRESULT hres; + + V_VT(&v) = VT_EMPTY; + hres = IWineJSDispatchHost_GetProperty(This->host_iface, idx, jsdisp->ctx->lcid, &v, &ei, + &jsdisp->ctx->jscaller->IServiceProvider_iface); + if(hres == DISP_E_EXCEPTION) + handle_dispatch_exception(jsdisp->ctx, &ei); + if(FAILED(hres)) + return hres; + + hres = variant_to_jsval(jsdisp->ctx, &v, r); + VariantClear(&v); + return hres; +} + +static HRESULT HostObject_prop_put(jsdisp_t *jsdisp, unsigned idx, jsval_t v) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + EXCEPINFO ei = { 0 }; + VARIANT var; + HRESULT hres; + + hres = jsval_to_variant(v, &var); + if(FAILED(hres)) + return hres; + + hres = IWineJSDispatchHost_SetProperty(This->host_iface, idx, jsdisp->ctx->lcid, &var, &ei, + &jsdisp->ctx->jscaller->IServiceProvider_iface); + if(hres == DISP_E_EXCEPTION) + handle_dispatch_exception(jsdisp->ctx, &ei); + VariantClear(&var); + return hres; +} + +static HRESULT HostObject_next_prop(jsdisp_t *jsdisp, unsigned id, struct property_info *desc) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + + return IWineJSDispatchHost_NextProperty(This->host_iface, id, desc); +} + +static const builtin_info_t HostObject_info = { + .class = JSCLASS_OBJECT, + .addref = HostObject_addref, + .release = HostObject_release, + .lookup_prop = HostObject_lookup_prop, + .prop_get = HostObject_prop_get, + .prop_put = HostObject_prop_put, + .next_prop = HostObject_next_prop, +}; + +HRESULT init_host_object(script_ctx_t *ctx, IWineJSDispatchHost *host_iface, IWineJSDispatch **ret) +{ + HostObject *host_obj; + HRESULT hres; + + if(!(host_obj = calloc(1, sizeof(*host_obj)))) + return E_OUTOFMEMORY; + + hres = init_dispex(&host_obj->jsdisp, ctx, &HostObject_info, ctx->object_prototype); + if(FAILED(hres)) { + free(host_obj); + return hres; + } + + host_obj->host_iface = host_iface; + *ret = &host_obj->jsdisp.IWineJSDispatch_iface; + return S_OK; +} diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index fc07c818edf..4d53e8a6832 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -47,6 +47,7 @@ typedef struct { IActiveScriptProperty IActiveScriptProperty_iface; IObjectSafety IObjectSafety_iface; IVariantChangeType IVariantChangeType_iface; + IWineJScript IWineJScript_iface;
LONG ref;
@@ -669,6 +670,9 @@ static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, }else if(IsEqualGUID(riid, &IID_IVariantChangeType)) { TRACE("(%p)->(IID_IVariantChangeType %p)\n", This, ppv); *ppv = &This->IVariantChangeType_iface; + }else if(IsEqualGUID(riid, &IID_IWineJScript)) { + TRACE("(%p)->(IID_IWineJScript %p)\n", This, ppv); + *ppv = &This->IWineJScript_iface; }
if(*ppv) { @@ -1424,6 +1428,43 @@ static const IVariantChangeTypeVtbl VariantChangeTypeVtbl = { VariantChangeType_ChangeType };
+static inline JScript *impl_from_IWineJScript(IWineJScript *iface) +{ + return CONTAINING_RECORD(iface, JScript, IWineJScript_iface); +} + +static HRESULT WINAPI WineJScript_QueryInterface(IWineJScript *iface, REFIID riid, void **ppv) +{ + JScript *This = impl_from_IWineJScript(iface); + return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); +} + +static ULONG WINAPI WineJScript_AddRef(IWineJScript *iface) +{ + JScript *This = impl_from_IWineJScript(iface); + return IActiveScript_AddRef(&This->IActiveScript_iface); +} + +static ULONG WINAPI WineJScript_Release(IWineJScript *iface) +{ + JScript *This = impl_from_IWineJScript(iface); + return IActiveScript_Release(&This->IActiveScript_iface); +} + +static HRESULT WINAPI WineJScript_InitHostObject(IWineJScript *iface, IWineJSDispatchHost *host_obj, + IWineJSDispatch **ret) +{ + JScript *This = impl_from_IWineJScript(iface); + return init_host_object(This->ctx, host_obj, ret); +} + +static const IWineJScriptVtbl WineJScriptVtbl = { + WineJScript_QueryInterface, + WineJScript_AddRef, + WineJScript_Release, + WineJScript_InitHostObject, +}; + HRESULT create_jscript_object(BOOL is_encode, REFIID riid, void **ppv) { JScript *ret; @@ -1441,6 +1482,7 @@ HRESULT create_jscript_object(BOOL is_encode, REFIID riid, void **ppv) ret->IActiveScriptProperty_iface.lpVtbl = &JScriptPropertyVtbl; ret->IObjectSafety_iface.lpVtbl = &JScriptSafetyVtbl; ret->IVariantChangeType_iface.lpVtbl = &VariantChangeTypeVtbl; + ret->IWineJScript_iface.lpVtbl = &WineJScriptVtbl; ret->ref = 1; ret->safeopt = INTERFACE_USES_DISPEX; ret->is_encode = is_encode; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 9454d9e3beb..29dec3297ca 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -237,6 +237,7 @@ enum jsdisp_enum_type { HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,jsdisp_t*,jsdisp_t**); HRESULT init_dispex(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*); HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*); +HRESULT init_host_object(script_ctx_t*,IWineJSDispatchHost*,IWineJSDispatch**);
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*); HRESULT disp_call_name(script_ctx_t*,IDispatch*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*); diff --git a/dlls/jscript/jscript_main.c b/dlls/jscript/jscript_main.c index ecbb5a713ab..6ccab362051 100644 --- a/dlls/jscript/jscript_main.c +++ b/dlls/jscript/jscript_main.c @@ -27,6 +27,7 @@ #include "mshtmhst.h" #include "rpcproxy.h" #include "jscript_classes.h" +#include "jsdisp.h"
#include "wine/debug.h"
diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index f053149c144..a794dbebe67 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -42,3 +42,28 @@ interface IWineJSDispatch : IDispatchEx { void Free(); } + +[ + object, + uuid(b1ebc544-6644-40c6-97f6-ccd9cc32bfba), + local +] +interface IWineJSDispatchHost : IDispatchEx +{ + HRESULT GetJSDispatch(IWineJSDispatch **ret); + HRESULT LookupProperty(const WCHAR *name, DWORD flags, struct property_info *desc); + HRESULT NextProperty(DISPID id, struct property_info *desc); + HRESULT GetProperty(DISPID id, LCID lcid, VARIANT *r, EXCEPINFO *ei, IServiceProvider *caller); + HRESULT SetProperty(DISPID id, LCID lcid, VARIANT *v, EXCEPINFO *ei, IServiceProvider *caller); + HRESULT CallFunction(DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); +} + +[ + object, + uuid(d359f2fe-5531-741b-a41a-5cf92edc971d), + local +] +interface IWineJScript : IUnknown +{ + HRESULT InitHostObject(IWineJSDispatchHost *host_obj, IWineJSDispatch **ret); +}
From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 16 ++++++++++++++++ dlls/jscript/jscript.h | 1 + dlls/jscript/jsdisp.idl | 1 + dlls/jscript/object.c | 16 +++++++++++----- 4 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index b684b9edd99..8c499fbd37b 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -3349,6 +3349,21 @@ static HRESULT HostObject_next_prop(jsdisp_t *jsdisp, unsigned id, struct proper return IWineJSDispatchHost_NextProperty(This->host_iface, id, desc); }
+static HRESULT HostObject_to_string(jsdisp_t *jsdisp, jsstr_t **ret) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + BSTR str; + HRESULT hres; + + hres = IWineJSDispatchHost_ToString(This->host_iface, &str); + if(FAILED(hres)) + return hres; + + *ret = jsstr_alloc(str); + SysFreeString(str); + return *ret ? S_OK : E_OUTOFMEMORY; +} + static const builtin_info_t HostObject_info = { .class = JSCLASS_OBJECT, .addref = HostObject_addref, @@ -3357,6 +3372,7 @@ static const builtin_info_t HostObject_info = { .prop_get = HostObject_prop_get, .prop_put = HostObject_prop_put, .next_prop = HostObject_next_prop, + .to_string = HostObject_to_string, };
HRESULT init_host_object(script_ctx_t *ctx, IWineJSDispatchHost *host_iface, IWineJSDispatch **ret) diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 29dec3297ca..a36291204b6 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -189,6 +189,7 @@ typedef struct { HRESULT (*next_prop)(jsdisp_t*,unsigned,struct property_info*); HRESULT (*prop_get)(jsdisp_t*,unsigned,jsval_t*); HRESULT (*prop_put)(jsdisp_t*,unsigned,jsval_t); + HRESULT (*to_string)(jsdisp_t*,jsstr_t**); HRESULT (*gc_traverse)(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*); } builtin_info_t;
diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index a794dbebe67..533677f6cad 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -56,6 +56,7 @@ interface IWineJSDispatchHost : IDispatchEx HRESULT GetProperty(DISPID id, LCID lcid, VARIANT *r, EXCEPINFO *ei, IServiceProvider *caller); HRESULT SetProperty(DISPID id, LCID lcid, VARIANT *v, EXCEPINFO *ei, IServiceProvider *caller); HRESULT CallFunction(DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); + HRESULT ToString(BSTR *str); }
[ diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 382f4107c45..da544c6b1c3 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -27,8 +27,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + const WCHAR *str = NULL; + jsstr_t *ret = NULL; jsdisp_t *jsdisp; - const WCHAR *str; IDispatch *disp; HRESULT hres;
@@ -74,6 +75,8 @@ static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns jsdisp = to_jsdisp(disp); if(!jsdisp) { str = L"[object Object]"; + }else if(jsdisp->builtin_info->to_string) { + hres = jsdisp->builtin_info->to_string(jsdisp, &ret); }else if(names[jsdisp->builtin_info->class]) { str = names[jsdisp->builtin_info->class]; }else { @@ -87,11 +90,14 @@ static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns
set_output: if(r) { - jsstr_t *ret; - ret = jsstr_alloc(str); - if(!ret) - return E_OUTOFMEMORY; + if(!ret) { + ret = jsstr_alloc(str); + if(!ret) + return E_OUTOFMEMORY; + } *r = jsval_string(ret); + }else if(ret) { + jsstr_release(ret); }
return S_OK;
From: Jacek Caban jacek@codeweavers.com
Based on patch by Gabriel Ivăncescu. --- dlls/jscript/dispex.c | 15 +++++++++++++++ dlls/jscript/engine.c | 20 +++++++++++++------- dlls/jscript/jscript.h | 1 + 3 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 8c499fbd37b..26d89ab2b5e 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -3393,3 +3393,18 @@ HRESULT init_host_object(script_ctx_t *ctx, IWineJSDispatchHost *host_iface, IWi *ret = &host_obj->jsdisp.IWineJSDispatch_iface; return S_OK; } + +IWineJSDispatchHost *get_host_dispatch(IDispatch *disp) +{ + HostObject *host_obj; + jsdisp_t *jsdisp; + + if(!(jsdisp = to_jsdisp(disp))) + return NULL; + if(jsdisp->builtin_info != &HostObject_info) + return NULL; + + host_obj = HostObject_from_jsdisp(jsdisp); + IWineJSDispatchHost_AddRef(host_obj->host_iface); + return host_obj->host_iface; +} diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 2be22a9b526..12e53435f16 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -637,14 +637,20 @@ static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret) return S_OK; }
- hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1); - if(FAILED(hres)) - return hres; + unk1 = (IUnknown *)get_host_dispatch(disp1); + if(!unk1) { + hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1); + if(FAILED(hres)) + return hres; + }
- hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2); - if(FAILED(hres)) { - IUnknown_Release(unk1); - return hres; + unk2 = (IUnknown *)get_host_dispatch(disp2); + if(!unk2) { + hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2); + if(FAILED(hres)) { + IUnknown_Release(unk1); + return hres; + } }
if(unk1 == unk2) { diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index a36291204b6..fdcead4a064 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -225,6 +225,7 @@ static inline IDispatchEx *to_dispex(jsdisp_t *jsdisp)
jsdisp_t *as_jsdisp(IDispatch*); jsdisp_t *to_jsdisp(IDispatch*); +IWineJSDispatchHost *get_host_dispatch(IDispatch*);
jsdisp_t *jsdisp_addref(jsdisp_t*); ULONG jsdisp_release(jsdisp_t*);
From: Jacek Caban jacek@codeweavers.com
Based on patch by Gabriel Ivăncescu. --- dlls/jscript/jsutils.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c index 12f41acd398..cb139977a84 100644 --- a/dlls/jscript/jsutils.c +++ b/dlls/jscript/jsutils.c @@ -279,15 +279,33 @@ HRESULT variant_to_jsval(script_ctx_t *ctx, VARIANT *var, jsval_t *r) *r = jsval_string(str); return S_OK; } - case VT_DISPATCH: { + case VT_DISPATCH: if(!V_DISPATCH(var)) { *r = ctx->html_mode ? jsval_null() : jsval_null_disp(); return S_OK; } + if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5) { + IWineJSDispatchHost *disp_host; + HRESULT hres; + hres = IDispatch_QueryInterface(V_DISPATCH(var), &IID_IWineJSDispatchHost, (void **)&disp_host); + if(SUCCEEDED(hres)) { + IWineJSDispatch *jsdisp_iface; + hres = IWineJSDispatchHost_GetJSDispatch(disp_host, &jsdisp_iface); + IWineJSDispatchHost_Release(disp_host); + if(SUCCEEDED(hres)) { + jsdisp_t *jsdisp = to_jsdisp((IDispatch *)jsdisp_iface); + if(jsdisp->ctx == ctx) { + *r = jsval_obj(jsdisp); + return S_OK; + }else { + jsdisp_release(jsdisp); + } + } + } + } IDispatch_AddRef(V_DISPATCH(var)); *r = jsval_disp(V_DISPATCH(var)); return S_OK; - } case VT_I1: *r = jsval_number(V_I1(var)); return S_OK; @@ -356,11 +374,18 @@ HRESULT jsval_to_variant(jsval_t val, VARIANT *retv) } V_VT(retv) = VT_NULL; return S_OK; - case JSV_OBJECT: + case JSV_OBJECT: { + IWineJSDispatchHost *host_disp = get_host_dispatch(get_object(val)); V_VT(retv) = VT_DISPATCH; + if(host_disp) { + V_DISPATCH(retv) = (IDispatch *)host_disp; + return S_OK; + } + V_DISPATCH(retv) = get_object(val); IDispatch_AddRef(get_object(val)); return S_OK; + } case JSV_STRING: V_VT(retv) = VT_BSTR; return jsstr_to_bstr(get_string(val), &V_BSTR(retv));
From: Jacek Caban jacek@codeweavers.com
Based on patch by Gabriel Ivăncescu. --- dlls/mshtml/dispex.c | 102 ++++++++++++++++++++++++++- dlls/mshtml/htmlwindow.c | 55 +++++++++++++++ dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/mshtml_private_iface.idl | 10 --- 4 files changed, 156 insertions(+), 12 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 2e436b364c4..a5526f2901c 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2243,7 +2243,90 @@ static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IWineJSDispatchHost *iface, return E_NOTIMPL; }
-static HRESULT WINAPI DispatchEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, +static HRESULT WINAPI JSDispatchHost_GetJSDispatch(IWineJSDispatchHost *iface, IWineJSDispatch **ret) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + FIXME("%p\n", This); + return E_NOINTERFACE; +} + +static HRESULT WINAPI JSDispatchHost_LookupProperty(IWineJSDispatchHost *iface, const WCHAR *name, DWORD flags, + struct property_info *desc) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + func_info_t *func; + DISPID id; + HRESULT hres; + + TRACE("%s (%p)->(%s)\n", This->info->desc->name, This, debugstr_w(name)); + + /* FIXME: name cast works as long as the object doesn't require the actual BSTR for its custom + * properties, we will need to fix it properly. */ + hres = get_builtin_id(This, (BSTR)name, flags, &id); + if(FAILED(hres)) + return hres; + + hres = get_builtin_func(This->info, id, &func); + if(FAILED(hres)) + return hres; + desc->id = id; + desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; + if(func->func_disp_idx < 0) + desc->flags |= PROPF_ENUMERABLE; + desc->name = func->name; + return S_OK; +} + +static HRESULT WINAPI JSDispatchHost_NextProperty(IWineJSDispatchHost *iface, DISPID id, struct property_info *desc) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + func_info_t *func; + HRESULT hres; + + TRACE("%s (%p)->(%lx)\n", This->info->desc->name, This, id); + + if(id == DISPID_STARTENUM) { + func = This->info->funcs; + }else { + hres = get_builtin_func(This->info, id, &func); + if(FAILED(hres)) + return hres; + func++; + } + + while(func < This->info->funcs + This->info->func_cnt) { + if(func->func_disp_idx == -1) { + desc->id = func->id; + desc->name = func->name; + desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; + return S_OK; + } + func++; + } + return S_FALSE; +} + +static HRESULT WINAPI JSDispatchHost_GetProperty(IWineJSDispatchHost *iface, DISPID id, LCID lcid, VARIANT *r, + EXCEPINFO *ei, IServiceProvider *caller) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + + TRACE("%s (%p)->(%lx)\n", This->info->desc->name, This, id); + + return dispex_prop_get(This, id, lcid, r, ei, caller); +} + +static HRESULT WINAPI JSDispatchHost_SetProperty(IWineJSDispatchHost *iface, DISPID id, LCID lcid, VARIANT *v, + EXCEPINFO *ei, IServiceProvider *caller) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + + TRACE("%s (%p)->(%lx)\n", This->info->desc->name, This, id); + + return dispex_prop_put(This, id, lcid, v, ei, caller); +} + +static HRESULT WINAPI JSDispatchHost_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { DispatchEx *This = impl_from_IWineJSDispatchHost(iface); @@ -2260,6 +2343,15 @@ static HRESULT WINAPI DispatchEx_CallFunction(IWineJSDispatchHost *iface, DISPID return call_builtin_function(This, func, dp, ret, ei, caller); }
+static HRESULT WINAPI JSDispatchHost_ToString(IWineJSDispatchHost *iface, BSTR *str) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + + TRACE("%s (%p)\n", This->info->desc->name, This); + + return dispex_to_string(This, str); +} + static IWineJSDispatchHostVtbl JSDispatchHostVtbl = { DispatchEx_QueryInterface, DispatchEx_AddRef, @@ -2276,7 +2368,13 @@ static IWineJSDispatchHostVtbl JSDispatchHostVtbl = { DispatchEx_GetMemberName, DispatchEx_GetNextDispID, DispatchEx_GetNameSpaceParent, - DispatchEx_CallFunction, + JSDispatchHost_GetJSDispatch, + JSDispatchHost_LookupProperty, + JSDispatchHost_NextProperty, + JSDispatchHost_GetProperty, + JSDispatchHost_SetProperty, + JSDispatchHost_CallFunction, + JSDispatchHost_ToString, };
static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb) diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index cf0920783d7..59abd1a857e 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3440,6 +3440,48 @@ static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IWineJSDispatchHost *iface return S_OK; }
+static HRESULT WINAPI WindowDispEx_GetJSDispatch(IWineJSDispatchHost *iface, IWineJSDispatch **ret) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_GetJSDispatch(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, ret); +} + +static HRESULT WINAPI WindowDispEx_LookupProperty(IWineJSDispatchHost *iface, const WCHAR *name, DWORD flags, + struct property_info *desc) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_LookupProperty(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, + name, flags, desc); +} + +static HRESULT WINAPI WindowDispEx_NextProperty(IWineJSDispatchHost *iface, DISPID id, struct property_info *desc) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_NextProperty(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, + id, desc); +} + +static HRESULT WINAPI WindowDispEx_GetProperty(IWineJSDispatchHost *iface, DISPID id, LCID lcid, VARIANT *r, + EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_GetProperty(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, + id, lcid, r, ei, caller); +} + +static HRESULT WINAPI WindowDispEx_SetProperty(IWineJSDispatchHost *iface, DISPID id, LCID lcid, VARIANT *v, + EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_SetProperty(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, + id, lcid, v, ei, caller); +} + static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { @@ -3449,6 +3491,13 @@ static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISP id, iid, dp, ret, ei, caller); }
+static HRESULT WINAPI WindowDispEx_ToString(IWineJSDispatchHost *iface, BSTR *str) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_ToString(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, str); +} + static const IWineJSDispatchHostVtbl WindowDispExVtbl = { WindowDispEx_QueryInterface, WindowDispEx_AddRef, @@ -3465,7 +3514,13 @@ static const IWineJSDispatchHostVtbl WindowDispExVtbl = { WindowDispEx_GetMemberName, WindowDispEx_GetNextDispID, WindowDispEx_GetNameSpaceParent, + WindowDispEx_GetJSDispatch, + WindowDispEx_LookupProperty, + WindowDispEx_NextProperty, + WindowDispEx_GetProperty, + WindowDispEx_SetProperty, WindowDispEx_CallFunction, + WindowDispEx_ToString, };
static inline HTMLOuterWindow *impl_from_IEventTarget(IEventTarget *iface) diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 1a8c666ae57..8520c2711eb 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -40,6 +40,7 @@ #include "nsiface.h"
#include "mshtml_private_iface.h" +#include "../jscript/jsdisp.h"
#include <assert.h>
diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl index f4292e298d0..503593d1c25 100644 --- a/dlls/mshtml/mshtml_private_iface.idl +++ b/dlls/mshtml/mshtml_private_iface.idl @@ -258,13 +258,3 @@ interface IWineXMLHttpRequestPrivate : IDispatch }
} /* library MSHTML_private */ - -[ - object, - uuid(d359f2fe-5531-741b-a41a-5cf92edc971b), - local -] -interface IWineJSDispatchHost : IDispatchEx -{ - HRESULT CallFunction(DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); -}
From: Jacek Caban jacek@codeweavers.com
Based on patch by Gabriel Ivăncescu. --- dlls/mshtml/dispex.c | 4 ++-- dlls/mshtml/htmlattr.c | 2 +- dlls/mshtml/htmlelem.c | 12 +++++++----- dlls/mshtml/htmlelemcol.c | 2 +- dlls/mshtml/htmlevent.c | 6 +++--- dlls/mshtml/htmlimg.c | 3 ++- dlls/mshtml/htmllocation.c | 2 +- dlls/mshtml/htmlnode.c | 2 +- dlls/mshtml/htmlselect.c | 3 ++- dlls/mshtml/htmlstorage.c | 3 ++- dlls/mshtml/htmlstyle.c | 2 +- dlls/mshtml/htmlstylesheet.c | 8 ++++---- dlls/mshtml/mshtml_private.h | 22 ++++++++++------------ dlls/mshtml/mutation.c | 4 ++-- dlls/mshtml/omnavigator.c | 30 ++++++++++++++++++------------ dlls/mshtml/range.c | 5 +++-- dlls/mshtml/selection.c | 3 ++- dlls/mshtml/xmlhttprequest.c | 3 ++- 18 files changed, 64 insertions(+), 52 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index a5526f2901c..ef83b508bde 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1069,7 +1069,7 @@ static func_disp_t *create_func_disp(DispatchEx *obj, func_info_t *info) if(!ret) return NULL;
- init_dispatch(&ret->dispex, &function_dispex, dispex_compat_mode(obj)); + init_dispatch(&ret->dispex, &function_dispex, NULL, dispex_compat_mode(obj)); ret->obj = obj; ret->info = info;
@@ -2499,7 +2499,7 @@ const void *dispex_get_vtbl(DispatchEx *dispex) return dispex->info->desc->vtbl; }
-void init_dispatch(DispatchEx *dispex, dispex_static_data_t *data, compat_mode_t compat_mode) +void init_dispatch(DispatchEx *dispex, dispex_static_data_t *data, HTMLInnerWindow *script_global, compat_mode_t compat_mode) { assert(compat_mode < COMPAT_MODE_CNT);
diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c index eaf7e4fc9c5..b9d3f82e84c 100644 --- a/dlls/mshtml/htmlattr.c +++ b/dlls/mshtml/htmlattr.c @@ -437,7 +437,7 @@ HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dis ret->dispid = dispid; ret->elem = elem;
- init_dispatch(&ret->dispex, &HTMLDOMAttribute_dispex, compat_mode); + init_dispatch(&ret->dispex, &HTMLDOMAttribute_dispex, NULL, compat_mode);
/* For attributes attached to an element, (elem,dispid) pair should be valid used for its operation. */ if(elem) { diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 1e20e75366a..581b50ee822 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -780,7 +780,7 @@ static HRESULT create_html_rect(nsIDOMClientRect *nsrect, compat_mode_t compat_m rect->IHTMLRect_iface.lpVtbl = &HTMLRectVtbl; rect->IHTMLRect2_iface.lpVtbl = &HTMLRect2Vtbl;
- init_dispatch(&rect->dispex, &HTMLRect_dispex, compat_mode); + init_dispatch(&rect->dispex, &HTMLRect_dispex, NULL, compat_mode);
nsIDOMClientRect_AddRef(nsrect); rect->nsrect = nsrect; @@ -3063,7 +3063,8 @@ static HRESULT WINAPI HTMLElement2_getClientRects(IHTMLElement2 *iface, IHTMLRec
rects->IHTMLRectCollection_iface.lpVtbl = &HTMLRectCollectionVtbl; rects->rect_list = rect_list; - init_dispatch(&rects->dispex, &HTMLRectCollection_dispex, dispex_compat_mode(&This->node.event_target.dispex)); + init_dispatch(&rects->dispex, &HTMLRectCollection_dispex, NULL, + dispex_compat_mode(&This->node.event_target.dispex));
*pRectCol = &rects->IHTMLRectCollection_iface; return S_OK; @@ -7179,7 +7180,7 @@ static HRESULT create_token_list(compat_mode_t compat_mode, IHTMLElement *elemen }
obj->IWineDOMTokenList_iface.lpVtbl = &WineDOMTokenListVtbl; - init_dispatch(&obj->dispex, &token_list_dispex, compat_mode); + init_dispatch(&obj->dispex, &token_list_dispex, NULL, compat_mode); IHTMLElement_AddRef(element); obj->element = element;
@@ -7536,7 +7537,7 @@ static HRESULT create_filters_collection(compat_mode_t compat_mode, IHTMLFilters
collection->IHTMLFiltersCollection_iface.lpVtbl = &HTMLFiltersCollectionVtbl;
- init_dispatch(&collection->dispex, &HTMLFiltersCollection_dispex, min(compat_mode, COMPAT_MODE_IE8)); + init_dispatch(&collection->dispex, &HTMLFiltersCollection_dispex, NULL, min(compat_mode, COMPAT_MODE_IE8));
*ret = &collection->IHTMLFiltersCollection_iface; return S_OK; @@ -8169,7 +8170,8 @@ HRESULT HTMLElement_get_attr_col(HTMLDOMNode *iface, HTMLAttributeCollection **a IHTMLDOMNode_AddRef(&This->node.IHTMLDOMNode_iface); This->attrs->elem = This; list_init(&This->attrs->attrs); - init_dispatch(&This->attrs->dispex, &HTMLAttributeCollection_dispex, dispex_compat_mode(&iface->event_target.dispex)); + init_dispatch(&This->attrs->dispex, &HTMLAttributeCollection_dispex, NULL, + dispex_compat_mode(&iface->event_target.dispex));
*ac = This->attrs; IHTMLAttributeCollection_AddRef(&This->attrs->IHTMLAttributeCollection_iface); diff --git a/dlls/mshtml/htmlelemcol.c b/dlls/mshtml/htmlelemcol.c index 191fa8cbc1e..92ea4584aa4 100644 --- a/dlls/mshtml/htmlelemcol.c +++ b/dlls/mshtml/htmlelemcol.c @@ -812,7 +812,7 @@ static IHTMLElementCollection *HTMLElementCollection_Create(HTMLElement **elems, ret->elems = elems; ret->len = len;
- init_dispatch(&ret->dispex, &HTMLElementCollection_dispex, compat_mode); + init_dispatch(&ret->dispex, &HTMLElementCollection_dispex, NULL, compat_mode);
TRACE("ret=%p len=%ld\n", ret, len);
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index dad7174681d..29bf94b9eea 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -1833,7 +1833,7 @@ static HTMLEventObj *alloc_event_obj(DOMEvent *event, compat_mode_t compat_mode) if(event) IDOMEvent_AddRef(&event->IDOMEvent_iface);
- init_dispatch(&event_obj->dispex, &HTMLEventObj_dispex, compat_mode); + init_dispatch(&event_obj->dispex, &HTMLEventObj_dispex, NULL, compat_mode); return event_obj; }
@@ -3761,7 +3761,7 @@ static void *event_ctor(unsigned size, dispex_static_data_t *dispex_data, nsIDOM
event->time_stamp = get_time_stamp();
- init_dispatch(&event->dispex, dispex_data, compat_mode); + init_dispatch(&event->dispex, dispex_data, NULL, compat_mode); return event; }
@@ -5118,7 +5118,7 @@ static int event_id_cmp(const void *key, const struct wine_rb_entry *entry)
void EventTarget_Init(EventTarget *event_target, dispex_static_data_t *dispex_data, compat_mode_t compat_mode) { - init_dispatch(&event_target->dispex, dispex_data, compat_mode); + init_dispatch(&event_target->dispex, dispex_data, NULL, compat_mode); event_target->IEventTarget_iface.lpVtbl = &EventTargetVtbl; wine_rb_init(&event_target->handler_map, event_id_cmp); } diff --git a/dlls/mshtml/htmlimg.c b/dlls/mshtml/htmlimg.c index 84eef1ad5ea..fb3be13b918 100644 --- a/dlls/mshtml/htmlimg.c +++ b/dlls/mshtml/htmlimg.c @@ -901,7 +901,8 @@ HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, HTMLImageElement ret->window = window; IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
- init_dispatch(&ret->dispex, &HTMLImageElementFactory_dispex, dispex_compat_mode(&window->event_target.dispex)); + init_dispatch(&ret->dispex, &HTMLImageElementFactory_dispex, NULL, + dispex_compat_mode(&window->event_target.dispex));
*ret_val = ret; return S_OK; diff --git a/dlls/mshtml/htmllocation.c b/dlls/mshtml/htmllocation.c index 1a5972b50ac..5c7e66c40df 100644 --- a/dlls/mshtml/htmllocation.c +++ b/dlls/mshtml/htmllocation.c @@ -606,7 +606,7 @@ HRESULT create_location(HTMLOuterWindow *window, HTMLLocation **ret) location->window = window; IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
- init_dispatch(&location->dispex, &HTMLLocation_dispex, COMPAT_MODE_QUIRKS); + init_dispatch(&location->dispex, &HTMLLocation_dispex, NULL, COMPAT_MODE_QUIRKS);
*ret = location; return S_OK; diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index 8f593371216..ceb50a17d02 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -418,7 +418,7 @@ HRESULT create_child_collection(nsIDOMNodeList *nslist, compat_mode_t compat_mod nsIDOMNodeList_AddRef(nslist); collection->nslist = nslist;
- init_dispatch(&collection->dispex, &HTMLDOMChildrenCollection_dispex, compat_mode); + init_dispatch(&collection->dispex, &HTMLDOMChildrenCollection_dispex, NULL, compat_mode);
*ret = &collection->IHTMLDOMChildrenCollection_iface; return S_OK; diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index 24affaea4ca..e85ed53c3d5 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -542,7 +542,8 @@ HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, HTMLOptionEleme ret->window = window; IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
- init_dispatch(&ret->dispex, &HTMLOptionElementFactory_dispex, dispex_compat_mode(&window->event_target.dispex)); + init_dispatch(&ret->dispex, &HTMLOptionElementFactory_dispex, NULL, + dispex_compat_mode(&window->event_target.dispex));
*ret_ptr = ret; return S_OK; diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index b865e5adc7e..174813a3fef 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -1451,7 +1451,8 @@ HRESULT create_html_storage(HTMLInnerWindow *window, BOOL local, IHTMLStorage ** storage->window = window; IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
- init_dispatch(&storage->dispex, &HTMLStorage_dispex, dispex_compat_mode(&window->event_target.dispex)); + init_dispatch(&storage->dispex, &HTMLStorage_dispex, NULL, + dispex_compat_mode(&window->event_target.dispex));
*p = &storage->IHTMLStorage_iface; return S_OK; diff --git a/dlls/mshtml/htmlstyle.c b/dlls/mshtml/htmlstyle.c index 5816139854f..def56f7aedb 100644 --- a/dlls/mshtml/htmlstyle.c +++ b/dlls/mshtml/htmlstyle.c @@ -9690,7 +9690,7 @@ void init_css_style(CSSStyle *style, nsIDOMCSSStyleDeclaration *nsstyle, dispex_ style->nsstyle = nsstyle; nsIDOMCSSStyleDeclaration_AddRef(nsstyle);
- init_dispatch(&style->dispex, dispex_info, compat_mode); + init_dispatch(&style->dispex, dispex_info, NULL, compat_mode); }
HRESULT HTMLStyle_Create(HTMLElement *elem, HTMLStyle **ret) diff --git a/dlls/mshtml/htmlstylesheet.c b/dlls/mshtml/htmlstylesheet.c index 1c8b52ddfba..711ef8b4042 100644 --- a/dlls/mshtml/htmlstylesheet.c +++ b/dlls/mshtml/htmlstylesheet.c @@ -183,7 +183,7 @@ static HRESULT create_style_sheet_rule(nsIDOMCSSRule *nsstylesheetrule, compat_m rule->IHTMLStyleSheetRule_iface.lpVtbl = &HTMLStyleSheetRuleVtbl; rule->nsstylesheetrule = NULL;
- init_dispatch(&rule->dispex, &HTMLStyleSheetRule_dispex, compat_mode); + init_dispatch(&rule->dispex, &HTMLStyleSheetRule_dispex, NULL, compat_mode);
if (nsstylesheetrule) { @@ -399,7 +399,7 @@ static HRESULT create_style_sheet_rules_collection(nsIDOMCSSRuleList *nslist, co collection->IHTMLStyleSheetRulesCollection_iface.lpVtbl = &HTMLStyleSheetRulesCollectionVtbl; collection->nslist = nslist;
- init_dispatch(&collection->dispex, &HTMLStyleSheetRulesCollection_dispex, compat_mode); + init_dispatch(&collection->dispex, &HTMLStyleSheetRulesCollection_dispex, NULL, compat_mode);
if(nslist) nsIDOMCSSRuleList_AddRef(nslist); @@ -779,7 +779,7 @@ HRESULT create_style_sheet_collection(nsIDOMStyleSheetList *nslist, compat_mode_ nsIDOMStyleSheetList_AddRef(nslist); collection->nslist = nslist;
- init_dispatch(&collection->dispex, &HTMLStyleSheetsCollection_dispex, compat_mode); + init_dispatch(&collection->dispex, &HTMLStyleSheetsCollection_dispex, NULL, compat_mode);
*ret = &collection->IHTMLStyleSheetsCollection_iface; return S_OK; @@ -1260,7 +1260,7 @@ HRESULT create_style_sheet(nsIDOMStyleSheet *nsstylesheet, compat_mode_t compat_ style_sheet->IHTMLStyleSheet4_iface.lpVtbl = &HTMLStyleSheet4Vtbl; style_sheet->nsstylesheet = NULL;
- init_dispatch(&style_sheet->dispex, &HTMLStyleSheet_dispex, compat_mode); + init_dispatch(&style_sheet->dispex, &HTMLStyleSheet_dispex, NULL, compat_mode);
if(nsstylesheet) { nsres = nsIDOMStyleSheet_QueryInterface(nsstylesheet, &IID_nsIDOMCSSStyleSheet, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 8520c2711eb..c14551ac5c1 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -78,11 +78,20 @@ #define MSHTML_E_NODOC 0x800a025c #define MSHTML_E_NOT_FUNC 0x800a138a
+typedef struct HTMLWindow HTMLWindow; +typedef struct HTMLInnerWindow HTMLInnerWindow; +typedef struct HTMLOuterWindow HTMLOuterWindow; +typedef struct HTMLDocumentNode HTMLDocumentNode; +typedef struct HTMLDocumentObj HTMLDocumentObj; +typedef struct HTMLFrameBase HTMLFrameBase; +typedef struct GeckoBrowser GeckoBrowser; +typedef struct HTMLAttributeCollection HTMLAttributeCollection; typedef struct DOMEvent DOMEvent; typedef struct HTMLDOMNode HTMLDOMNode; typedef struct ConnectionPoint ConnectionPoint; typedef struct BSCallback BSCallback; typedef struct EventTarget EventTarget; +typedef struct ScriptHost ScriptHost;
#define TID_LIST \ XIID(NULL) \ @@ -481,7 +490,7 @@ extern void (__cdecl *ccp_init)(ExternalCycleCollectionParticipant*,const CCObjC extern void (__cdecl *describe_cc_node)(nsCycleCollectingAutoRefCnt*,const char*,nsCycleCollectionTraversalCallback*); extern void (__cdecl *note_cc_edge)(nsISupports*,const char*,nsCycleCollectionTraversalCallback*);
-void init_dispatch(DispatchEx*,dispex_static_data_t*,compat_mode_t); +void init_dispatch(DispatchEx*,dispex_static_data_t*,HTMLInnerWindow*,compat_mode_t); void dispex_props_unlink(DispatchEx*); HRESULT change_type(VARIANT*,VARIANT*,VARTYPE,IServiceProvider*); HRESULT dispex_get_dprop_ref(DispatchEx*,const WCHAR*,BOOL,VARIANT**); @@ -505,17 +514,6 @@ typedef enum {
dispex_prop_type_t get_dispid_type(DISPID);
-typedef struct HTMLWindow HTMLWindow; -typedef struct HTMLInnerWindow HTMLInnerWindow; -typedef struct HTMLOuterWindow HTMLOuterWindow; -typedef struct HTMLDocumentNode HTMLDocumentNode; -typedef struct HTMLDocumentObj HTMLDocumentObj; -typedef struct HTMLFrameBase HTMLFrameBase; -typedef struct GeckoBrowser GeckoBrowser; -typedef struct HTMLAttributeCollection HTMLAttributeCollection; - -typedef struct ScriptHost ScriptHost; - typedef enum { GLOBAL_SCRIPTVAR, GLOBAL_ELEMENTVAR, diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 290174e4785..a502e3c9427 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -1200,7 +1200,7 @@ static HRESULT create_mutation_observer(compat_mode_t compat_mode, IDispatch *ca }
obj->IWineMSHTMLMutationObserver_iface.lpVtbl = &WineMSHTMLMutationObserverVtbl; - init_dispatch(&obj->dispex, &mutation_observer_dispex, compat_mode); + init_dispatch(&obj->dispex, &mutation_observer_dispex, NULL, compat_mode);
IDispatch_AddRef(callback); obj->callback = callback; @@ -1299,7 +1299,7 @@ HRESULT create_mutation_observer_ctor(compat_mode_t compat_mode, IDispatch **ret return E_OUTOFMEMORY; }
- init_dispatch(&obj->dispex, &mutation_observer_ctor_dispex, compat_mode); + init_dispatch(&obj->dispex, &mutation_observer_ctor_dispex, NULL, compat_mode);
*ret = (IDispatch *)&obj->dispex.IWineJSDispatchHost_iface; return S_OK; diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 69a47c2706d..4ee76a585a1 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -242,7 +242,7 @@ HRESULT create_dom_implementation(HTMLDocumentNode *doc_node, IHTMLDOMImplementa dom_implementation->IHTMLDOMImplementation2_iface.lpVtbl = &HTMLDOMImplementation2Vtbl; dom_implementation->browser = doc_node->browser;
- init_dispatch(&dom_implementation->dispex, &HTMLDOMImplementation_dispex, doc_node->document_mode); + init_dispatch(&dom_implementation->dispex, &HTMLDOMImplementation_dispex, NULL, doc_node->document_mode);
nsres = nsIDOMDocument_GetImplementation(doc_node->dom_document, &dom_implementation->implementation); if(NS_FAILED(nsres)) { @@ -435,7 +435,7 @@ HRESULT create_html_screen(compat_mode_t compat_mode, IHTMLScreen **ret)
screen->IHTMLScreen_iface.lpVtbl = &HTMLSreenVtbl;
- init_dispatch(&screen->dispex, &HTMLScreen_dispex, compat_mode); + init_dispatch(&screen->dispex, &HTMLScreen_dispex, NULL, compat_mode);
*ret = &screen->IHTMLScreen_iface; return S_OK; @@ -566,7 +566,8 @@ HRESULT create_history(HTMLInnerWindow *window, OmHistory **ret) if(!history) return E_OUTOFMEMORY;
- init_dispatch(&history->dispex, &OmHistory_dispex, dispex_compat_mode(&window->event_target.dispex)); + init_dispatch(&history->dispex, &OmHistory_dispex, NULL, + dispex_compat_mode(&window->event_target.dispex)); history->IOmHistory_iface.lpVtbl = &OmHistoryVtbl;
history->window = window; @@ -682,7 +683,8 @@ static HRESULT create_plugins_collection(OmNavigator *navigator, HTMLPluginsColl col->IHTMLPluginsCollection_iface.lpVtbl = &HTMLPluginsCollectionVtbl; col->navigator = navigator;
- init_dispatch(&col->dispex, &HTMLPluginsCollection_dispex, dispex_compat_mode(&navigator->dispex)); + init_dispatch(&col->dispex, &HTMLPluginsCollection_dispex, NULL, + dispex_compat_mode(&navigator->dispex));
*ret = col; return S_OK; @@ -783,7 +785,8 @@ static HRESULT create_mime_types_collection(OmNavigator *navigator, HTMLMimeType col->IHTMLMimeTypesCollection_iface.lpVtbl = &HTMLMimeTypesCollectionVtbl; col->navigator = navigator;
- init_dispatch(&col->dispex, &HTMLMimeTypesCollection_dispex, dispex_compat_mode(&navigator->dispex)); + init_dispatch(&col->dispex, &HTMLMimeTypesCollection_dispex, NULL, + dispex_compat_mode(&navigator->dispex));
*ret = col; return S_OK; @@ -1164,7 +1167,7 @@ HRESULT create_navigator(compat_mode_t compat_mode, IOmNavigator **navigator)
ret->IOmNavigator_iface.lpVtbl = &OmNavigatorVtbl;
- init_dispatch(&ret->dispex, &OmNavigator_dispex, compat_mode); + init_dispatch(&ret->dispex, &OmNavigator_dispex, NULL, compat_mode);
*navigator = &ret->IOmNavigator_iface; return S_OK; @@ -1682,7 +1685,8 @@ static HRESULT WINAPI HTMLPerformance_get_navigation(IHTMLPerformance *iface, navigation->window = This->window; IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
- init_dispatch(&navigation->dispex, &HTMLPerformanceNavigation_dispex, dispex_compat_mode(&This->dispex)); + init_dispatch(&navigation->dispex, &HTMLPerformanceNavigation_dispex, NULL, + dispex_compat_mode(&This->dispex));
This->navigation = &navigation->IHTMLPerformanceNavigation_iface; } @@ -1708,7 +1712,8 @@ static HRESULT WINAPI HTMLPerformance_get_timing(IHTMLPerformance *iface, IHTMLP timing->window = This->window; IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
- init_dispatch(&timing->dispex, &HTMLPerformanceTiming_dispex, dispex_compat_mode(&This->dispex)); + init_dispatch(&timing->dispex, &HTMLPerformanceTiming_dispex, NULL, + dispex_compat_mode(&This->dispex));
This->timing = &timing->IHTMLPerformanceTiming_iface; } @@ -1822,7 +1827,7 @@ HRESULT create_performance(HTMLInnerWindow *window, IHTMLPerformance **ret) performance->window = window; IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
- init_dispatch(&performance->dispex, &HTMLPerformance_dispex, compat_mode); + init_dispatch(&performance->dispex, &HTMLPerformance_dispex, NULL, compat_mode);
*ret = &performance->IHTMLPerformance_iface; return S_OK; @@ -1922,7 +1927,7 @@ HRESULT create_namespace_collection(compat_mode_t compat_mode, IHTMLNamespaceCol return E_OUTOFMEMORY;
namespaces->IHTMLNamespaceCollection_iface.lpVtbl = &HTMLNamespaceCollectionVtbl; - init_dispatch(&namespaces->dispex, &HTMLNamespaceCollection_dispex, compat_mode); + init_dispatch(&namespaces->dispex, &HTMLNamespaceCollection_dispex, NULL, compat_mode); *ret = &namespaces->IHTMLNamespaceCollection_iface; return S_OK; } @@ -2126,7 +2131,7 @@ void create_console(compat_mode_t compat_mode, IWineMSHTMLConsole **ret) }
obj->IWineMSHTMLConsole_iface.lpVtbl = &WineMSHTMLConsoleVtbl; - init_dispatch(&obj->dispex, &console_dispex, compat_mode); + init_dispatch(&obj->dispex, &console_dispex, NULL, compat_mode);
*ret = &obj->IWineMSHTMLConsole_iface; } @@ -2442,7 +2447,8 @@ HRESULT create_media_query_list(HTMLWindow *window, BSTR media_query, IDispatch
media_query_list->IWineMSHTMLMediaQueryList_iface.lpVtbl = &media_query_list_vtbl; list_init(&media_query_list->listeners); - init_dispatch(&media_query_list->dispex, &media_query_list_dispex, dispex_compat_mode(&window->inner_window->event_target.dispex)); + init_dispatch(&media_query_list->dispex, &media_query_list_dispex, NULL, + dispex_compat_mode(&window->inner_window->event_target.dispex));
*ret = (IDispatch*)&media_query_list->IWineMSHTMLMediaQueryList_iface; return S_OK; diff --git a/dlls/mshtml/range.c b/dlls/mshtml/range.c index e6d265bc2b0..10f9de09ca8 100644 --- a/dlls/mshtml/range.c +++ b/dlls/mshtml/range.c @@ -1699,7 +1699,8 @@ HRESULT HTMLTxtRange_Create(HTMLDocumentNode *doc, nsIDOMRange *nsrange, IHTMLTx if(!ret) return E_OUTOFMEMORY;
- init_dispatch(&ret->dispex, &HTMLTxtRange_dispex, dispex_compat_mode(&doc->node.event_target.dispex)); + init_dispatch(&ret->dispex, &HTMLTxtRange_dispex, NULL, + dispex_compat_mode(&doc->node.event_target.dispex));
ret->IHTMLTxtRange_iface.lpVtbl = &HTMLTxtRangeVtbl; ret->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl; @@ -2004,7 +2005,7 @@ HRESULT create_dom_range(nsIDOMRange *nsrange, compat_mode_t compat_mode, IHTMLD if(!ret) return E_OUTOFMEMORY;
- init_dispatch(&ret->dispex, &HTMLDOMRange_dispex, compat_mode); + init_dispatch(&ret->dispex, &HTMLDOMRange_dispex, NULL, compat_mode);
ret->IHTMLDOMRange_iface.lpVtbl = &HTMLDOMRangeVtbl;
diff --git a/dlls/mshtml/selection.c b/dlls/mshtml/selection.c index fdf2be9acd5..8c457f1813f 100644 --- a/dlls/mshtml/selection.c +++ b/dlls/mshtml/selection.c @@ -253,7 +253,8 @@ HRESULT HTMLSelectionObject_Create(HTMLDocumentNode *doc, nsISelection *nsselect if(!selection) return E_OUTOFMEMORY;
- init_dispatch(&selection->dispex, &HTMLSelectionObject_dispex, dispex_compat_mode(&doc->node.event_target.dispex)); + init_dispatch(&selection->dispex, &HTMLSelectionObject_dispex, NULL, + dispex_compat_mode(&doc->node.event_target.dispex));
selection->IHTMLSelectionObject_iface.lpVtbl = &HTMLSelectionObjectVtbl; selection->IHTMLSelectionObject2_iface.lpVtbl = &HTMLSelectionObject2Vtbl; diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 4d170c66e44..efb343e6f16 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1665,7 +1665,8 @@ HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, HTMLXMLHttpReq ret->window = window; IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
- init_dispatch(&ret->dispex, &HTMLXMLHttpRequestFactory_dispex, dispex_compat_mode(&window->event_target.dispex)); + init_dispatch(&ret->dispex, &HTMLXMLHttpRequestFactory_dispex, NULL, + dispex_compat_mode(&window->event_target.dispex));
*ret_ptr = ret; return S_OK;
From: Jacek Caban jacek@codeweavers.com
Based on patch by Gabriel Ivăncescu. --- dlls/mshtml/dispex.c | 53 ++++++++++++++++++++++++++++++++---- dlls/mshtml/htmlscript.h | 1 + dlls/mshtml/htmlwindow.c | 1 + dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/script.c | 17 ++++++++++++ 5 files changed, 69 insertions(+), 5 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index ef83b508bde..61e7dae650e 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -28,6 +28,7 @@ #include "wine/debug.h"
#include "mshtml_private.h" +#include "htmlscript.h"
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
@@ -1710,14 +1711,31 @@ HRESULT dispex_to_string(DispatchEx *dispex, BSTR *ret) return *ret ? S_OK : E_OUTOFMEMORY; }
-static dispex_data_t *ensure_dispex_info(dispex_static_data_t *desc, compat_mode_t compat_mode) +static dispex_data_t *ensure_dispex_info(DispatchEx *dispex, dispex_static_data_t *desc, + compat_mode_t compat_mode, HTMLInnerWindow *script_global) { + HRESULT hres; + if(!desc->info_cache[compat_mode]) { EnterCriticalSection(&cs_dispex_static_data); if(!desc->info_cache[compat_mode]) desc->info_cache[compat_mode] = preprocess_dispex_data(desc, compat_mode); LeaveCriticalSection(&cs_dispex_static_data); + if(!desc->info_cache[compat_mode]) + return NULL; } + + if(compat_mode >= COMPAT_MODE_IE9 && script_global) { + if(!script_global->jscript) + initialize_script_global(script_global); + if(script_global->jscript) { + hres = IWineJScript_InitHostObject(script_global->jscript, &dispex->IWineJSDispatchHost_iface, + &dispex->jsdisp); + if(FAILED(hres)) + ERR("Failed to initialize jsdisp: %08lx\n", hres); + } + } + return desc->info_cache[compat_mode]; }
@@ -1726,7 +1744,7 @@ static BOOL ensure_real_info(DispatchEx *dispex) if(dispex->info != dispex->info->desc->delayed_init_info) return TRUE;
- dispex->info = ensure_dispex_info(dispex->info->desc, dispex_compat_mode(dispex)); + dispex->info = ensure_dispex_info(dispex, dispex->info->desc, dispex_compat_mode(dispex), NULL); return dispex->info != NULL; }
@@ -1872,6 +1890,8 @@ static HRESULT WINAPI DispatchEx_GetDispID(IWineJSDispatchHost *iface, BSTR bstr
if(!ensure_real_info(This)) return E_OUTOFMEMORY; + if(This->jsdisp) + return IWineJSDispatch_GetDispID(This->jsdisp, bstrName, grfdex, pid);
hres = get_builtin_id(This, bstrName, grfdex, pid); if(hres != DISP_E_UNKNOWNNAME) @@ -2048,6 +2068,9 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IWineJSDispatchHost *iface, DISPID id, return hres; }
+ if(This->jsdisp) + return IWineJSDispatch_InvokeEx(This->jsdisp, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); + switch(wFlags) { case DISPATCH_PROPERTYGET: if(!pvarRes) @@ -2076,6 +2099,10 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IWineJSDispatchHost *iface,
TRACE("%s (%p)->(%s %lx)\n", This->info->desc->name, This, debugstr_w(name), grfdex);
+ if(!ensure_real_info(This)) + return E_OUTOFMEMORY; + if(This->jsdisp) + return IWineJSDispatch_DeleteMemberByName(This->jsdisp, name, grfdex); if(dispex_compat_mode(This) < COMPAT_MODE_IE8 && !This->info->desc->vtbl->delete) return E_NOTIMPL;
@@ -2096,6 +2123,10 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IWineJSDispatchHost *iface
TRACE("%s (%p)->(%lx)\n", This->info->desc->name, This, id);
+ if(!ensure_real_info(This)) + return E_OUTOFMEMORY; + if(This->jsdisp) + return IWineJSDispatch_DeleteMemberByDispID(This->jsdisp, id); if(is_custom_dispid(id) && This->info->desc->vtbl->delete) return This->info->desc->vtbl->delete(This, id);
@@ -2137,6 +2168,8 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IWineJSDispatchHost *iface, DISPI
if(!ensure_real_info(This)) return E_OUTOFMEMORY; + if(This->jsdisp) + return IWineJSDispatch_GetMemberName(This->jsdisp, id, pbstrName);
if(is_custom_dispid(id)) { if(This->info->desc->vtbl->get_name) @@ -2192,6 +2225,8 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IWineJSDispatchHost *iface, DWORD
if(!ensure_real_info(This)) return E_OUTOFMEMORY; + if(This->jsdisp) + return IWineJSDispatch_GetNextDispID(This->jsdisp, grfdex, id, pid);
if(is_dynamic_dispid(id)) { DWORD idx = id - DISPID_DYNPROP_0; @@ -2246,8 +2281,12 @@ static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IWineJSDispatchHost *iface, static HRESULT WINAPI JSDispatchHost_GetJSDispatch(IWineJSDispatchHost *iface, IWineJSDispatch **ret) { DispatchEx *This = impl_from_IWineJSDispatchHost(iface); - FIXME("%p\n", This); - return E_NOINTERFACE; + + if(!This->jsdisp) + return E_NOINTERFACE; + *ret = This->jsdisp; + IWineJSDispatch_AddRef(*ret); + return S_OK; }
static HRESULT WINAPI JSDispatchHost_LookupProperty(IWineJSDispatchHost *iface, const WCHAR *name, DWORD flags, @@ -2449,6 +2488,7 @@ static nsresult NSAPI dispex_unlink(void *p) static void NSAPI dispex_delete_cycle_collectable(void *p) { DispatchEx *This = impl_from_IWineJSDispatchHost(p); + IWineJSDispatch *jsdisp = This->jsdisp; dynamic_prop_t *prop;
if(This->info->desc->vtbl->unlink) @@ -2482,6 +2522,8 @@ static void NSAPI dispex_delete_cycle_collectable(void *p)
destructor: This->info->desc->vtbl->destructor(This); + if(jsdisp) + IWineJSDispatch_Free(jsdisp); }
void init_dispex_cc(void) @@ -2505,6 +2547,7 @@ void init_dispatch(DispatchEx *dispex, dispex_static_data_t *data, HTMLInnerWind
dispex->IWineJSDispatchHost_iface.lpVtbl = &JSDispatchHostVtbl; dispex->dynamic_data = NULL; + dispex->jsdisp = NULL; ccref_init(&dispex->ccref, 1);
if(data->vtbl->get_compat_mode) { @@ -2522,6 +2565,6 @@ void init_dispatch(DispatchEx *dispex, dispex_static_data_t *data, HTMLInnerWind } dispex->info = data->delayed_init_info; }else { - dispex->info = ensure_dispex_info(data, compat_mode); + dispex->info = ensure_dispex_info(dispex, data, compat_mode, script_global); } } diff --git a/dlls/mshtml/htmlscript.h b/dlls/mshtml/htmlscript.h index 8384ace573a..37a7b8d1f50 100644 --- a/dlls/mshtml/htmlscript.h +++ b/dlls/mshtml/htmlscript.h @@ -50,3 +50,4 @@ void update_browser_script_mode(GeckoBrowser*,IUri*); BOOL find_global_prop(HTMLInnerWindow*,BSTR,DWORD,ScriptHost**,DISPID*); IDispatch *get_script_disp(ScriptHost*); IActiveScriptSite *get_first_script_site(HTMLInnerWindow*); +void initialize_script_global(HTMLInnerWindow*); diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 59abd1a857e..31976b73d04 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -135,6 +135,7 @@ static void detach_inner_window(HTMLInnerWindow *window) abort_window_bindings(window); remove_target_tasks(window->task_magic); release_script_hosts(window); + unlink_ref(&window->jscript); window->base.outer_window = NULL;
if(outer_window && outer_window->base.inner_window == window) { diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index c14551ac5c1..461eb3a93f2 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -427,6 +427,7 @@ struct DispatchEx {
nsCycleCollectingAutoRefCnt ccref;
+ IWineJSDispatch *jsdisp; dispex_data_t *info; dispex_dynamic_data_t *dynamic_data; }; @@ -631,6 +632,7 @@ struct HTMLInnerWindow {
struct list children; struct list script_hosts; + IWineJScript *jscript;
IHTMLEventObj *event;
diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index b1f24f9d8d3..6a542defa8c 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -1388,6 +1388,23 @@ static ScriptHost *get_script_host(HTMLInnerWindow *window, const GUID *guid) return create_script_host(window, guid); }
+void initialize_script_global(HTMLInnerWindow *script_global) +{ + ScriptHost *script_host; + HRESULT hres; + + if(script_global->jscript) + return; + + script_host = get_script_host(script_global, &CLSID_JScript); + if(!script_host) + return; + + hres = IActiveScript_QueryInterface(script_host->script, &IID_IWineJScript, (void **)&script_global->jscript); + if(FAILED(hres)) + ERR("Could not get IWineJScript, don't use native jscript.dll\n"); +} + static ScriptHost *get_elem_script_host(HTMLInnerWindow *window, HTMLScriptElement *script_elem) { GUID guid;
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/htmlwindow.c | 2 +- dlls/mshtml/mshtml_private.h | 2 +- dlls/mshtml/omnavigator.c | 5 ++-- dlls/mshtml/tests/documentmode.js | 2 +- dlls/mshtml/tests/es5.js | 45 +++++++++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 31976b73d04..7cf4bf9738b 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -1216,7 +1216,7 @@ static HRESULT WINAPI HTMLWindow2_get_screen(IHTMLWindow2 *iface, IHTMLScreen ** if(!window->screen) { HRESULT hres;
- hres = create_html_screen(dispex_compat_mode(&window->event_target.dispex), &window->screen); + hres = create_html_screen(window, &window->screen); if(FAILED(hres)) return hres; } diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 461eb3a93f2..a5e0f309ed9 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1040,7 +1040,7 @@ HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,HTMLImageElementFactory* HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,HTMLXMLHttpRequestFactory**); HRESULT create_location(HTMLOuterWindow*,HTMLLocation**); HRESULT create_navigator(compat_mode_t,IOmNavigator**); -HRESULT create_html_screen(compat_mode_t,IHTMLScreen**); +HRESULT create_html_screen(HTMLInnerWindow*,IHTMLScreen**); HRESULT create_performance(HTMLInnerWindow*,IHTMLPerformance**); HRESULT create_history(HTMLInnerWindow*,OmHistory**); HRESULT create_namespace_collection(compat_mode_t,IHTMLNamespaceCollection**); diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 4ee76a585a1..88dfa1b5bf9 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -425,7 +425,7 @@ static dispex_static_data_t HTMLScreen_dispex = { HTMLScreen_iface_tids };
-HRESULT create_html_screen(compat_mode_t compat_mode, IHTMLScreen **ret) +HRESULT create_html_screen(HTMLInnerWindow *window, IHTMLScreen **ret) { HTMLScreen *screen;
@@ -435,7 +435,8 @@ HRESULT create_html_screen(compat_mode_t compat_mode, IHTMLScreen **ret)
screen->IHTMLScreen_iface.lpVtbl = &HTMLSreenVtbl;
- init_dispatch(&screen->dispex, &HTMLScreen_dispex, NULL, compat_mode); + init_dispatch(&screen->dispex, &HTMLScreen_dispex, window, + dispex_compat_mode(&window->event_target.dispex));
*ret = &screen->IHTMLScreen_iface; return S_OK; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index c8ce01b0443..2cffff79479 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -242,7 +242,7 @@ sync_test("builtin_toString", function() { ok(s === (tostr ? tostr : (v < 9 ? "[object]" : "[object " + name + "]")), msg + " toString returned " + s); } s = Object.prototype.toString.call(obj); - todo_wine_if(v >= 9 && name != "Object"). + todo_wine_if(v >= 9 && name != "Object" && name != "Screen"). ok(s === (v < 9 ? "[object Object]" : "[object " + name + "]"), msg + " Object.toString returned " + s); }
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 353d0b0b5c0..b1340918fad 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2601,3 +2601,48 @@ sync_test("initProgressEvent", function() { ok(e.loaded === 99, "loaded after re-init = " + e.loaded); ok(e.total === 50, "total after re-init = " + e.total); }); + +sync_test("screen", function() { + var o = screen; + + ok(typeof(o) == "object", "typeof(o) = " + typeof(o)); + ok(o instanceof Object, "o is not an instance of Object"); + + o.prop = 1; + ok(o.prop === 1, "o.prop = " + o.prop); + ok(o.hasOwnProperty("prop"), 'o.hasOwnProperty("prop") = ' + o.hasOwnProperty("prop")); + test_own_data_prop_desc(o, "prop", true, true, true); + + Object.defineProperty(o, "defprop", {writable: false, enumerable: false, configurable: true, value: 2}); + ok(o.defprop === 2, "o.prop = " + o.prop); + test_own_data_prop_desc(o, "defprop", false, false, true); + + ok(typeof(Object.keys(o)) === "object", "Object.keys(o) = " + Object.keys(o)); + ok(Object.isExtensible(o) === true, "Object.isExtensible(o) = " + Object.isExtensible(o)); + ok(Object.isFrozen(o) === false, "Object.isFrozen(o) = " + Object.isFrozen(o)); + ok(Object.isSealed(o) === false, "Object.isSealed(o) = " + Object.isSealed(o)); + + Object.seal(o); + test_own_data_prop_desc(o, "prop", true, true, false); + test_own_data_prop_desc(o, "defprop", false, false, false); + ok(Object.isExtensible(o) === false, "Object.isExtensible(o) = " + Object.isExtensible(o)); + ok(Object.isFrozen(o) === false, "Object.isFrozen(o) = " + Object.isFrozen(o)); + ok(Object.isSealed(o) === true, "Object.isSealed(o) = " + Object.isSealed(o)); + + o.prop2 = 3; + ok(!("prop2" in o), "o.prop2 = " + o.prop2); + + function check_enum(o, name) { + var ret = 0; + for(var iter in o) { + if(iter == name) ret++; + } + ok(ret < 2, name + " enumerated " + ret + " times"); + return ret != 0; + } + ok(check_enum(o, "width"), "width not enumerated"); + ok(check_enum(o, "height"), "height not enumerated"); + ok(check_enum(o, "prop"), "prop not enumerated"); + ok(!check_enum(o, "defprop"), "defprop enumerated"); + ok(!check_enum(o, "prop2"), "prop2 enumerated"); +});
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146919
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/jscript/Makefile.in:20 error: patch failed: dlls/jscript/dispex.c:1831 error: patch failed: dlls/jscript/jscript.h:28 error: patch failed: dlls/jscript/jsdisp.idl:25 error: patch failed: dlls/jscript/jsdisp.idl:42 error: patch failed: dlls/jscript/jsdisp.idl:56 error: patch failed: dlls/jscript/dispex.c:3393 error: patch failed: dlls/jscript/engine.c:637 error: patch failed: dlls/jscript/jscript.h:225 error: patch failed: dlls/jscript/jsutils.c:279 error: patch failed: dlls/mshtml/dispex.c:2243 error: patch failed: dlls/mshtml/htmlwindow.c:3440 error: patch failed: dlls/mshtml/mshtml_private.h:40 error: patch failed: dlls/mshtml/mshtml_private_iface.idl:258 error: patch failed: dlls/mshtml/dispex.c:1069 error: patch failed: dlls/mshtml/htmlattr.c:437 error: patch failed: dlls/mshtml/htmlelem.c:780 error: patch failed: dlls/mshtml/htmlelemcol.c:812 error: patch failed: dlls/mshtml/htmlevent.c:1833 error: patch failed: dlls/mshtml/htmlimg.c:901 error: patch failed: dlls/mshtml/htmllocation.c:606 error: patch failed: dlls/mshtml/htmlnode.c:418 error: patch failed: dlls/mshtml/htmlselect.c:542 error: patch failed: dlls/mshtml/htmlstorage.c:1451 error: patch failed: dlls/mshtml/htmlstyle.c:9690 error: patch failed: dlls/mshtml/htmlstylesheet.c:183 error: patch failed: dlls/mshtml/mshtml_private.h:78 error: patch failed: dlls/mshtml/mutation.c:1200 error: patch failed: dlls/mshtml/omnavigator.c:242 error: patch failed: dlls/mshtml/range.c:1699 error: patch failed: dlls/mshtml/selection.c:253 error: patch failed: dlls/mshtml/xmlhttprequest.c:1665 error: patch failed: dlls/mshtml/dispex.c:28 error: patch failed: dlls/mshtml/htmlscript.h:50 error: patch failed: dlls/mshtml/htmlwindow.c:135 error: patch failed: dlls/mshtml/mshtml_private.h:427 error: patch failed: dlls/mshtml/script.c:1388 error: patch failed: dlls/mshtml/omnavigator.c:435 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/jscript/Makefile.in:20 error: patch failed: dlls/jscript/dispex.c:1831 error: patch failed: dlls/jscript/jscript.h:28 error: patch failed: dlls/jscript/jsdisp.idl:25 error: patch failed: dlls/jscript/jsdisp.idl:42 error: patch failed: dlls/jscript/jsdisp.idl:56 error: patch failed: dlls/jscript/dispex.c:3393 error: patch failed: dlls/jscript/engine.c:637 error: patch failed: dlls/jscript/jscript.h:225 error: patch failed: dlls/jscript/jsutils.c:279 error: patch failed: dlls/mshtml/dispex.c:2243 error: patch failed: dlls/mshtml/htmlwindow.c:3440 error: patch failed: dlls/mshtml/mshtml_private.h:40 error: patch failed: dlls/mshtml/mshtml_private_iface.idl:258 error: patch failed: dlls/mshtml/dispex.c:1069 error: patch failed: dlls/mshtml/htmlattr.c:437 error: patch failed: dlls/mshtml/htmlelem.c:780 error: patch failed: dlls/mshtml/htmlelemcol.c:812 error: patch failed: dlls/mshtml/htmlevent.c:1833 error: patch failed: dlls/mshtml/htmlimg.c:901 error: patch failed: dlls/mshtml/htmllocation.c:606 error: patch failed: dlls/mshtml/htmlnode.c:418 error: patch failed: dlls/mshtml/htmlselect.c:542 error: patch failed: dlls/mshtml/htmlstorage.c:1451 error: patch failed: dlls/mshtml/htmlstyle.c:9690 error: patch failed: dlls/mshtml/htmlstylesheet.c:183 error: patch failed: dlls/mshtml/mshtml_private.h:78 error: patch failed: dlls/mshtml/mutation.c:1200 error: patch failed: dlls/mshtml/omnavigator.c:242 error: patch failed: dlls/mshtml/range.c:1699 error: patch failed: dlls/mshtml/selection.c:253 error: patch failed: dlls/mshtml/xmlhttprequest.c:1665 error: patch failed: dlls/mshtml/dispex.c:28 error: patch failed: dlls/mshtml/htmlscript.h:50 error: patch failed: dlls/mshtml/htmlwindow.c:135 error: patch failed: dlls/mshtml/mshtml_private.h:427 error: patch failed: dlls/mshtml/script.c:1388 error: patch failed: dlls/mshtml/omnavigator.c:435 Task: Patch failed to apply
=== debian11b (build log) ===
error: patch failed: dlls/jscript/Makefile.in:20 error: patch failed: dlls/jscript/dispex.c:1831 error: patch failed: dlls/jscript/jscript.h:28 error: patch failed: dlls/jscript/jsdisp.idl:25 error: patch failed: dlls/jscript/jsdisp.idl:42 error: patch failed: dlls/jscript/jsdisp.idl:56 error: patch failed: dlls/jscript/dispex.c:3393 error: patch failed: dlls/jscript/engine.c:637 error: patch failed: dlls/jscript/jscript.h:225 error: patch failed: dlls/jscript/jsutils.c:279 error: patch failed: dlls/mshtml/dispex.c:2243 error: patch failed: dlls/mshtml/htmlwindow.c:3440 error: patch failed: dlls/mshtml/mshtml_private.h:40 error: patch failed: dlls/mshtml/mshtml_private_iface.idl:258 error: patch failed: dlls/mshtml/dispex.c:1069 error: patch failed: dlls/mshtml/htmlattr.c:437 error: patch failed: dlls/mshtml/htmlelem.c:780 error: patch failed: dlls/mshtml/htmlelemcol.c:812 error: patch failed: dlls/mshtml/htmlevent.c:1833 error: patch failed: dlls/mshtml/htmlimg.c:901 error: patch failed: dlls/mshtml/htmllocation.c:606 error: patch failed: dlls/mshtml/htmlnode.c:418 error: patch failed: dlls/mshtml/htmlselect.c:542 error: patch failed: dlls/mshtml/htmlstorage.c:1451 error: patch failed: dlls/mshtml/htmlstyle.c:9690 error: patch failed: dlls/mshtml/htmlstylesheet.c:183 error: patch failed: dlls/mshtml/mshtml_private.h:78 error: patch failed: dlls/mshtml/mutation.c:1200 error: patch failed: dlls/mshtml/omnavigator.c:242 error: patch failed: dlls/mshtml/range.c:1699 error: patch failed: dlls/mshtml/selection.c:253 error: patch failed: dlls/mshtml/xmlhttprequest.c:1665 error: patch failed: dlls/mshtml/dispex.c:28 error: patch failed: dlls/mshtml/htmlscript.h:50 error: patch failed: dlls/mshtml/htmlwindow.c:135 error: patch failed: dlls/mshtml/mshtml_private.h:427 error: patch failed: dlls/mshtml/script.c:1388 error: patch failed: dlls/mshtml/omnavigator.c:435 Task: Patch failed to apply
The new version fixes (inaccurate) GCC warning.