mirror of
https://github.com/reactos/wine.git
synced 2024-12-04 17:56:51 +00:00
mshtml: Hook addEventListener InvokeEx calls to allow capture default value.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5bc2e83c7a
commit
d84f6f72cc
@ -52,6 +52,7 @@ typedef struct {
|
||||
DISPID id;
|
||||
BSTR name;
|
||||
tid_t tid;
|
||||
dispex_hook_invoke_t hook;
|
||||
SHORT call_vtbl_off;
|
||||
SHORT put_vtbl_off;
|
||||
SHORT get_vtbl_off;
|
||||
@ -230,7 +231,8 @@ static BOOL is_arg_type_supported(VARTYPE vt)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void add_func_info(dispex_data_t *data, tid_t tid, const FUNCDESC *desc, ITypeInfo *dti)
|
||||
static void add_func_info(dispex_data_t *data, tid_t tid, const FUNCDESC *desc, ITypeInfo *dti,
|
||||
dispex_hook_invoke_t hook)
|
||||
{
|
||||
func_info_t *info;
|
||||
BSTR name;
|
||||
@ -262,6 +264,7 @@ static void add_func_info(dispex_data_t *data, tid_t tid, const FUNCDESC *desc,
|
||||
info->tid = tid;
|
||||
info->func_disp_idx = -1;
|
||||
info->prop_vt = VT_EMPTY;
|
||||
info->hook = hook;
|
||||
}else {
|
||||
SysFreeString(name);
|
||||
}
|
||||
@ -326,10 +329,9 @@ static void add_func_info(dispex_data_t *data, tid_t tid, const FUNCDESC *desc,
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT process_interface(dispex_data_t *data, tid_t tid, ITypeInfo *disp_typeinfo, const DISPID *blacklist_dispids)
|
||||
static HRESULT process_interface(dispex_data_t *data, tid_t tid, ITypeInfo *disp_typeinfo, const dispex_hook_t *hooks)
|
||||
{
|
||||
unsigned i = 7; /* skip IDispatch functions */
|
||||
const DISPID *blacklist_iter;
|
||||
ITypeInfo *typeinfo;
|
||||
FUNCDESC *funcdesc;
|
||||
HRESULT hres;
|
||||
@ -339,20 +341,25 @@ static HRESULT process_interface(dispex_data_t *data, tid_t tid, ITypeInfo *disp
|
||||
return hres;
|
||||
|
||||
while(1) {
|
||||
const dispex_hook_t *hook = NULL;
|
||||
|
||||
hres = ITypeInfo_GetFuncDesc(typeinfo, i++, &funcdesc);
|
||||
if(FAILED(hres))
|
||||
break;
|
||||
|
||||
if(blacklist_dispids) {
|
||||
for(blacklist_iter = blacklist_dispids; *blacklist_iter != DISPID_UNKNOWN; blacklist_iter++) {
|
||||
if(*blacklist_iter == funcdesc->memid)
|
||||
if(hooks) {
|
||||
for(hook = hooks; hook->dispid != DISPID_UNKNOWN; hook++) {
|
||||
if(hook->dispid == funcdesc->memid)
|
||||
break;
|
||||
}
|
||||
if(hook->dispid == DISPID_UNKNOWN)
|
||||
hook = NULL;
|
||||
}
|
||||
|
||||
if(!blacklist_dispids || *blacklist_iter == DISPID_UNKNOWN) {
|
||||
if(!hook || hook->invoke) {
|
||||
TRACE("adding...\n");
|
||||
add_func_info(data, tid, funcdesc, disp_typeinfo ? disp_typeinfo : typeinfo);
|
||||
add_func_info(data, tid, funcdesc, disp_typeinfo ? disp_typeinfo : typeinfo,
|
||||
hook ? hook->invoke : NULL);
|
||||
}
|
||||
|
||||
ITypeInfo_ReleaseFuncDesc(typeinfo, funcdesc);
|
||||
@ -361,11 +368,11 @@ static HRESULT process_interface(dispex_data_t *data, tid_t tid, ITypeInfo *disp
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void dispex_info_add_interface(dispex_data_t *info, tid_t tid, const DISPID *blacklist_dispids)
|
||||
void dispex_info_add_interface(dispex_data_t *info, tid_t tid, const dispex_hook_t *hooks)
|
||||
{
|
||||
HRESULT hres;
|
||||
|
||||
hres = process_interface(info, tid, NULL, blacklist_dispids);
|
||||
hres = process_interface(info, tid, NULL, hooks);
|
||||
if(FAILED(hres))
|
||||
ERR("process_interface failed: %08x\n", hres);
|
||||
}
|
||||
@ -1239,6 +1246,12 @@ static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(func->hook) {
|
||||
hres = func->hook(This, lcid, flags, dp, res, ei, caller);
|
||||
if(hres != S_FALSE)
|
||||
return hres;
|
||||
}
|
||||
|
||||
if(func->func_disp_idx != -1)
|
||||
return function_invoke(This, func, flags, dp, res, ei, caller);
|
||||
|
||||
|
@ -5398,11 +5398,14 @@ static IHTMLEventObj *HTMLElement_set_current_event(DispatchEx *dispex, IHTMLEve
|
||||
|
||||
void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
|
||||
{
|
||||
static const DISPID elem2_ie11_blacklist[] = {DISPID_IHTMLELEMENT2_DOSCROLL, DISPID_UNKNOWN};
|
||||
static const dispex_hook_t elem2_ie11_hooks[] = {
|
||||
{DISPID_IHTMLELEMENT2_DOSCROLL, NULL},
|
||||
{DISPID_UNKNOWN}
|
||||
};
|
||||
|
||||
HTMLDOMNode_init_dispex_info(info, mode);
|
||||
|
||||
dispex_info_add_interface(info, IHTMLElement2_tid, mode >= COMPAT_MODE_IE11 ? elem2_ie11_blacklist : NULL);
|
||||
dispex_info_add_interface(info, IHTMLElement2_tid, mode >= COMPAT_MODE_IE11 ? elem2_ie11_hooks : NULL);
|
||||
|
||||
if(mode >= COMPAT_MODE_IE8)
|
||||
dispex_info_add_interface(info, IElementSelector_tid, NULL);
|
||||
|
@ -2051,6 +2051,11 @@ static inline EventTarget *impl_from_IEventTarget(IEventTarget *iface)
|
||||
return CONTAINING_RECORD(iface, EventTarget, IEventTarget_iface);
|
||||
}
|
||||
|
||||
static inline EventTarget *impl_from_DispatchEx(DispatchEx *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, EventTarget, dispex);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI EventTarget_QueryInterface(IEventTarget *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
EventTarget *This = impl_from_IEventTarget(iface);
|
||||
@ -2162,6 +2167,27 @@ static HRESULT WINAPI EventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent *
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, LCID lcid, WORD flags,
|
||||
DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
/* If only two arguments were given, implicitly set capture to false */
|
||||
if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
|
||||
VARIANT args[3];
|
||||
DISPPARAMS new_dp = {args, NULL, 3, 0};
|
||||
V_VT(args) = VT_BOOL;
|
||||
V_BOOL(args) = VARIANT_FALSE;
|
||||
args[1] = dp->rgvarg[0];
|
||||
args[2] = dp->rgvarg[1];
|
||||
|
||||
TRACE("implicit capture\n");
|
||||
|
||||
return IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IEVENTTARGET_ADDEVENTLISTENER,
|
||||
lcid, flags, &new_dp, res, ei, caller);
|
||||
}
|
||||
|
||||
return S_FALSE; /* fallback to default */
|
||||
}
|
||||
|
||||
static const IEventTargetVtbl EventTargetVtbl = {
|
||||
EventTarget_QueryInterface,
|
||||
EventTarget_AddRef,
|
||||
@ -2210,8 +2236,13 @@ HRESULT EventTarget_QI(EventTarget *event_target, REFIID riid, void **ppv)
|
||||
|
||||
void EventTarget_init_dispex_info(dispex_data_t *dispex_info, compat_mode_t compat_mode)
|
||||
{
|
||||
static const dispex_hook_t IEventTarget_hooks[] = {
|
||||
{DISPID_IEVENTTARGET_ADDEVENTLISTENER, IEventTarget_addEventListener_hook},
|
||||
{DISPID_UNKNOWN}
|
||||
};
|
||||
|
||||
if(compat_mode >= COMPAT_MODE_IE9)
|
||||
dispex_info_add_interface(dispex_info, IEventTarget_tid, NULL);
|
||||
dispex_info_add_interface(dispex_info, IEventTarget_tid, IEventTarget_hooks);
|
||||
}
|
||||
|
||||
static int event_id_cmp(const void *key, const struct wine_rb_entry *entry)
|
||||
|
@ -283,6 +283,14 @@ typedef struct {
|
||||
dispex_data_t *delayed_init_info;
|
||||
} dispex_static_data_t;
|
||||
|
||||
typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,
|
||||
EXCEPINFO*,IServiceProvider*);
|
||||
|
||||
typedef struct {
|
||||
DISPID dispid;
|
||||
dispex_hook_invoke_t invoke;
|
||||
} dispex_hook_t;
|
||||
|
||||
struct DispatchEx {
|
||||
IDispatchEx IDispatchEx_iface;
|
||||
|
||||
@ -331,7 +339,7 @@ void dispex_unlink(DispatchEx*) DECLSPEC_HIDDEN;
|
||||
void release_typelib(void) DECLSPEC_HIDDEN;
|
||||
HRESULT get_class_typeinfo(const CLSID*,ITypeInfo**) DECLSPEC_HIDDEN;
|
||||
const void *dispex_get_vtbl(DispatchEx*) DECLSPEC_HIDDEN;
|
||||
void dispex_info_add_interface(dispex_data_t*,tid_t,const DISPID*) DECLSPEC_HIDDEN;
|
||||
void dispex_info_add_interface(dispex_data_t*,tid_t,const dispex_hook_t*) DECLSPEC_HIDDEN;
|
||||
compat_mode_t dispex_compat_mode(DispatchEx*) DECLSPEC_HIDDEN;
|
||||
|
||||
static inline void init_dispex(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *desc)
|
||||
|
@ -62,6 +62,7 @@ function test_listener_order() {
|
||||
document.body.onclick = record_call("body.onclick");
|
||||
document.body.addEventListener("click", record_call("body.click(capture)"), true);
|
||||
document.body.addEventListener("click", record_call("body.click(bubble)"), false);
|
||||
document.body.addEventListener("click", record_call("body.click(bubble2)"));
|
||||
document.body.attachEvent("onclick", record_call("body.click(attached)"));
|
||||
|
||||
div.attachEvent("onclick", record_call("div.click(attached)"));
|
||||
@ -74,9 +75,9 @@ function test_listener_order() {
|
||||
div.click();
|
||||
ok(calls === "window.click(capture),document.click(capture),body.click(capture),"
|
||||
+ "div.click(attached),div.click(bubble),div.onclick,div.click(capture1),"
|
||||
+ "div.click(capture2),body.onclick,body.click(bubble),body.click(attached),"
|
||||
+ "document.click(attached),document.click(bubble),document.onclick,"
|
||||
+ "window.click(bubble),", "calls = " + calls);
|
||||
+ "div.click(capture2),body.onclick,body.click(bubble),body.click(bubble2),"
|
||||
+ "body.click(attached),document.click(attached),document.click(bubble),"
|
||||
+ "document.onclick,window.click(bubble),", "calls = " + calls);
|
||||
|
||||
div.onclick = record_call("new div.onclick");
|
||||
|
||||
@ -84,9 +85,9 @@ function test_listener_order() {
|
||||
div.click();
|
||||
ok(calls === "window.click(capture),document.click(capture),body.click(capture),"
|
||||
+ "div.click(attached),div.click(bubble),new div.onclick,div.click(capture1),"
|
||||
+ "div.click(capture2),body.onclick,body.click(bubble),body.click(attached),"
|
||||
+ "document.click(attached),document.click(bubble),document.onclick,"
|
||||
+ "window.click(bubble),", "calls = " + calls);
|
||||
+ "div.click(capture2),body.onclick,body.click(bubble),body.click(bubble2),"
|
||||
+ "body.click(attached),document.click(attached),document.click(bubble),"
|
||||
+ "document.onclick,window.click(bubble),", "calls = " + calls);
|
||||
|
||||
next_test();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user