Jacek Caban : mshtml: Store current IHTMLEventObj in DOMEvent and create it in fire_event_obj if needed.

Alexandre Julliard julliard at winehq.org
Fri Oct 20 15:09:36 CDT 2017


Module: wine
Branch: master
Commit: aaa576463c0caf015bdd3f8bff9f92f27ce44351
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=aaa576463c0caf015bdd3f8bff9f92f27ce44351

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Oct 20 15:09:15 2017 +0200

mshtml: Store current IHTMLEventObj in DOMEvent and create it in fire_event_obj if needed.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mshtml/htmlevent.c      | 59 +++++++++++++++++++++++++-------------------
 dlls/mshtml/htmlevent.h      |  6 +++--
 dlls/mshtml/xmlhttprequest.c |  3 ++-
 3 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 02e4363..6314b14 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -223,7 +223,7 @@ static eventid_t attr_to_eid(const WCHAR *str)
     return EVENTID_LAST;
 }
 
-struct HTMLEventObj {
+typedef struct {
     DispatchEx dispex;
     IHTMLEventObj IHTMLEventObj_iface;
 
@@ -232,7 +232,7 @@ struct HTMLEventObj {
     const event_info_t *type;
     DOMEvent *event;
     VARIANT return_value;
-};
+} HTMLEventObj;
 
 static inline HTMLEventObj *impl_from_IHTMLEventObj(IHTMLEventObj *iface)
 {
@@ -1204,7 +1204,7 @@ static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
     return hres;
 }
 
-static HRESULT call_cp_func(IDispatch *disp, DISPID dispid, HTMLEventObj *event_obj, VARIANT *retv)
+static HRESULT call_cp_func(IDispatch *disp, DISPID dispid, IHTMLEventObj *event_obj, VARIANT *retv)
 {
     DISPPARAMS dp = {NULL,NULL,0,0};
     VARIANT event_arg;
@@ -1213,7 +1213,7 @@ static HRESULT call_cp_func(IDispatch *disp, DISPID dispid, HTMLEventObj *event_
 
     if(event_obj) {
         V_VT(&event_arg) = VT_DISPATCH;
-        V_DISPATCH(&event_arg) = (IDispatch*)&event_obj->IHTMLEventObj_iface;
+        V_DISPATCH(&event_arg) = (IDispatch*)event_obj;
         dp.rgvarg = &event_arg;
         dp.cArgs = 1;
     }
@@ -1252,7 +1252,7 @@ static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid)
     return FALSE;
 }
 
-void call_event_handlers(HTMLEventObj *event_obj, EventTarget *event_target, DOMEvent *event)
+void call_event_handlers(EventTarget *event_target, DOMEvent *event)
 {
     const eventid_t eid = event->event_id;
     handler_vector_t *handler_vector = get_handler_vector(event_target, eid, FALSE);
@@ -1299,7 +1299,7 @@ void call_event_handlers(HTMLEventObj *event_obj, EventTarget *event_target, DOM
         int i;
 
         V_VT(&arg) = VT_DISPATCH;
-        V_DISPATCH(&arg) = (IDispatch*)&event_obj->dispex.IDispatchEx_iface;
+        V_DISPATCH(&arg) = (IDispatch*)event->event_obj;
 
         i = handler_vector->handler_cnt;
         while(i--) {
@@ -1347,7 +1347,7 @@ void call_event_handlers(HTMLEventObj *event_obj, EventTarget *event_target, DOM
 
                     TRACE("cp %s [%u] >>>\n", debugstr_w(event_info[eid].name), i);
                     hres = call_cp_func(cp->sinks[i].disp, event_info[eid].dispid,
-                            cp->data->pass_event_arg ? event_obj : NULL, &v);
+                            cp->data->pass_event_arg ? event->event_obj : NULL, &v);
                     if(hres == S_OK) {
                         TRACE("cp %s [%u] <<<\n", debugstr_w(event_info[eid].name), i);
 
@@ -1370,11 +1370,12 @@ void call_event_handlers(HTMLEventObj *event_obj, EventTarget *event_target, DOM
     }
 }
 
-static void fire_event_obj(EventTarget *event_target, DOMEvent *event, HTMLEventObj *event_obj)
+static void fire_event_obj(EventTarget *event_target, DOMEvent *event)
 {
     EventTarget *target_chain_buf[8], **target_chain = target_chain_buf;
     unsigned chain_cnt, chain_buf_size, i;
     const event_target_vtbl_t *vtbl, *target_vtbl;
+    HTMLEventObj *event_obj_ref = NULL;
     IHTMLEventObj *prev_event = NULL;
     EventTarget *iter;
     DWORD event_flags;
@@ -1418,15 +1419,23 @@ static void fire_event_obj(EventTarget *event_target, DOMEvent *event, HTMLEvent
         iter = vtbl->get_parent_event_target(&iter->dispex);
     } while(iter);
 
+    if(!event->event_obj && !event->no_event_obj) {
+        event_obj_ref = alloc_event_obj(event);
+        if(event_obj_ref) {
+            event_obj_ref->type = event_info + event->event_id;
+            event->event_obj = &event_obj_ref->IHTMLEventObj_iface;
+        }
+    }
+
     target_vtbl = dispex_get_vtbl(&event_target->dispex);
     if(target_vtbl && target_vtbl->set_current_event)
-        prev_event = target_vtbl->set_current_event(&event_target->dispex, event_obj ? &event_obj->IHTMLEventObj_iface : NULL);
+        prev_event = target_vtbl->set_current_event(&event_target->dispex, event->event_obj);
 
     event->target = event_target;
     IDispatchEx_AddRef(&event_target->dispex.IDispatchEx_iface);
 
     for(i = 0; i < chain_cnt; i++) {
-        call_event_handlers(event_obj, target_chain[i], event);
+        call_event_handlers(target_chain[i], event);
         if(!(event_flags & EVENT_BUBBLES) || event->stop_propagation)
             break;
     }
@@ -1452,6 +1461,11 @@ static void fire_event_obj(EventTarget *event_target, DOMEvent *event, HTMLEvent
         }
     }
 
+    if(event_obj_ref) {
+        event->event_obj = NULL;
+        IHTMLEventObj_Release(&event_obj_ref->IHTMLEventObj_iface);
+    }
+
     for(i = 0; i < chain_cnt; i++)
         IDispatchEx_Release(&target_chain[i]->dispex.IDispatchEx_iface);
     if(target_chain != target_chain_buf)
@@ -1460,7 +1474,6 @@ static void fire_event_obj(EventTarget *event_target, DOMEvent *event, HTMLEvent
 
 void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, EventTarget *target, nsIDOMEvent *nsevent)
 {
-    HTMLEventObj *event_obj = NULL;
     DOMEvent *event;
     HRESULT hres;
 
@@ -1471,19 +1484,11 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, EventTarge
     if(FAILED(hres))
         return;
 
-    if(set_event) {
-        event_obj = alloc_event_obj(event);
-        if(!event_obj) {
-            IDOMEvent_Release(&event->IDOMEvent_iface);
-            return;
-        }
-        event_obj->type = event_info + eid;
-    }
+    if(!set_event)
+        event->no_event_obj = TRUE;
 
-    fire_event_obj(target, event, event_obj);
+    fire_event_obj(target, event);
 
-    if(event_obj)
-        IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
     IDOMEvent_Release(&event->IDOMEvent_iface);
 }
 
@@ -1533,11 +1538,13 @@ HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *even
     if(!event_obj->event)
         hres = create_document_event(node->doc, eid, &event_obj->event);
 
-    if(SUCCEEDED(hres))
-        fire_event_obj(&node->event_target, event_obj->event, event_obj);
+    if(SUCCEEDED(hres)) {
+        event_obj->event->event_obj = &event_obj->IHTMLEventObj_iface;
+        fire_event_obj(&node->event_target, event_obj->event);
+        event_obj->event->event_obj = NULL;
+    }
 
-    if(event_obj)
-        IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
+    IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
     if(FAILED(hres))
         return hres;
 
diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h
index 76b971f..f348076 100644
--- a/dlls/mshtml/htmlevent.h
+++ b/dlls/mshtml/htmlevent.h
@@ -66,6 +66,9 @@ typedef struct {
     EventTarget *target;
     BOOL prevent_default;
     BOOL stop_propagation;
+
+    IHTMLEventObj *event_obj;
+    BOOL no_event_obj;
 } DOMEvent;
 
 eventid_t str_to_eid(LPCWSTR) DECLSPEC_HIDDEN;
@@ -84,8 +87,7 @@ HRESULT create_event_obj(IHTMLEventObj**) DECLSPEC_HIDDEN;
 void bind_target_event(HTMLDocumentNode*,EventTarget*,const WCHAR*,IDispatch*) DECLSPEC_HIDDEN;
 HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode*,eventid_t) DECLSPEC_HIDDEN;
 
-typedef struct HTMLEventObj HTMLEventObj;
-void call_event_handlers(HTMLEventObj*,EventTarget*,DOMEvent*);
+void call_event_handlers(EventTarget*,DOMEvent*);
 
 HRESULT create_document_event_str(HTMLDocumentNode*,const WCHAR*,IDOMEvent**) DECLSPEC_HIDDEN;
 HRESULT create_event_from_nsevent(nsIDOMEvent*,DOMEvent**) DECLSPEC_HIDDEN;
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c
index 1563870..cc7a5e0 100644
--- a/dlls/mshtml/xmlhttprequest.c
+++ b/dlls/mshtml/xmlhttprequest.c
@@ -194,7 +194,8 @@ static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *i
 
     hres = create_event_from_nsevent(nsevent, &event);
     if(SUCCEEDED(hres) ){
-        call_event_handlers(NULL, &This->xhr->event_target, event);
+        event->no_event_obj = TRUE;
+        call_event_handlers(&This->xhr->event_target, event);
         IDOMEvent_Release(&event->IDOMEvent_iface);
     }
     return NS_OK;




More information about the wine-cvs mailing list