Jacek Caban : mshtml: Store event handlers in rb tree.

Alexandre Julliard julliard at winehq.org
Tue Feb 14 16:24:51 CST 2017


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Feb 13 21:12:33 2017 +0100

mshtml: Store event handlers in rb tree.

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

---

 dlls/mshtml/htmlevent.c      | 89 ++++++++++++++++++++++----------------------
 dlls/mshtml/htmlevent.h      |  1 +
 dlls/mshtml/htmlnode.c       |  1 +
 dlls/mshtml/htmlwindow.c     |  1 +
 dlls/mshtml/mshtml_private.h |  3 +-
 dlls/mshtml/xmlhttprequest.c |  1 +
 6 files changed, 49 insertions(+), 47 deletions(-)

diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 7d11747..27e041c 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -36,15 +36,13 @@
 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
 
 typedef struct {
+    struct wine_rb_entry entry;
+    eventid_t event_id;
     IDispatch *handler_prop;
     DWORD handler_cnt;
     IDispatch **handlers;
 } handler_vector_t;
 
-struct event_target_t {
-    handler_vector_t *event_table[EVENTID_LAST];
-};
-
 static const WCHAR abortW[] = {'a','b','o','r','t',0};
 static const WCHAR onabortW[] = {'o','n','a','b','o','r','t',0};
 
@@ -899,37 +897,35 @@ HRESULT create_event_obj(IHTMLEventObj **ret)
     return S_OK;
 }
 
-static inline event_target_t *get_event_target_data(EventTarget *event_target, BOOL alloc)
+static handler_vector_t *get_handler_vector(EventTarget *event_target, eventid_t eid, BOOL alloc)
 {
-    const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
+    const dispex_static_data_vtbl_t *vtbl;
+    handler_vector_t *handler_vector;
+    struct wine_rb_entry *entry;
 
-    if(vtbl && vtbl->get_event_target)
+    vtbl = dispex_get_vtbl(&event_target->dispex);
+    if(vtbl->get_event_target)
         event_target = vtbl->get_event_target(&event_target->dispex);
-    if(event_target->ptr || !alloc)
-        return event_target->ptr;
 
-    return event_target->ptr = heap_alloc_zero(sizeof(event_target_t));
-}
-
-static handler_vector_t *get_handler_vector(EventTarget *event_target, eventid_t eid, BOOL alloc)
-{
-    event_target_t *data;
+    entry = wine_rb_get(&event_target->handler_map, (const void*)eid);
+    if(entry)
+        return WINE_RB_ENTRY_VALUE(entry, handler_vector_t, entry);
+    if(!alloc)
+        return NULL;
 
-    data = get_event_target_data(event_target, alloc);
-    if(!data)
+    handler_vector = heap_alloc_zero(sizeof(*handler_vector));
+    if(!handler_vector)
         return NULL;
 
-    if(alloc && !data->event_table[eid]) {
-        data->event_table[eid] = heap_alloc_zero(sizeof(*data->event_table[eid]));
-        if(data->event_table[eid]) {
-            const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
-            if(vtbl->bind_event)
-                vtbl->bind_event(&event_target->dispex, eid);
-            else
-                FIXME("Unsupported event binding on target %p\n", event_target);
-        }
-    }
-    return data->event_table[eid];
+    handler_vector->event_id = eid;
+    vtbl = dispex_get_vtbl(&event_target->dispex);
+    if(vtbl->bind_event)
+        vtbl->bind_event(&event_target->dispex, eid);
+    else
+        FIXME("Unsupported event binding on target %p\n", event_target);
+
+    wine_rb_put(&event_target->handler_map, (const void*)eid, &handler_vector->entry);
+    return handler_vector;
 }
 
 static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
@@ -1642,25 +1638,28 @@ HRESULT doc_init_events(HTMLDocumentNode *doc)
     return S_OK;
 }
 
-void release_event_target(EventTarget *event_target)
+static int event_id_cmp(const void *key, const struct wine_rb_entry *entry)
 {
-    int i;
-    unsigned int j;
+    return (INT_PTR)key - WINE_RB_ENTRY_VALUE(entry, handler_vector_t, entry)->event_id;
+}
 
-    if(!event_target->ptr)
-        return;
+void init_event_target(EventTarget *event_target)
+{
+    wine_rb_init(&event_target->handler_map, event_id_cmp);
+}
 
-    for(i=0; i < EVENTID_LAST; i++) {
-        if(event_target->ptr->event_table[i]) {
-            if(event_target->ptr->event_table[i]->handler_prop)
-                IDispatch_Release(event_target->ptr->event_table[i]->handler_prop);
-            for(j=0; j < event_target->ptr->event_table[i]->handler_cnt; j++)
-                if(event_target->ptr->event_table[i]->handlers[j])
-                    IDispatch_Release(event_target->ptr->event_table[i]->handlers[j]);
-            heap_free(event_target->ptr->event_table[i]->handlers);
-            heap_free(event_target->ptr->event_table[i]);
-        }
-    }
+void release_event_target(EventTarget *event_target)
+{
+    handler_vector_t *iter, *iter2;
+    unsigned i;
 
-    heap_free(event_target->ptr);
+    WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter, iter2, &event_target->handler_map, handler_vector_t, entry) {
+        if(iter->handler_prop)
+            IDispatch_Release(iter->handler_prop);
+        for(i = 0; i < iter->handler_cnt; i++)
+            if(iter->handlers[i])
+                IDispatch_Release(iter->handlers[i]);
+        heap_free(iter->handlers);
+        heap_free(iter);
+    }
 }
diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h
index d66f359..5bdd435 100644
--- a/dlls/mshtml/htmlevent.h
+++ b/dlls/mshtml/htmlevent.h
@@ -55,6 +55,7 @@ typedef enum {
 
 eventid_t str_to_eid(LPCWSTR) DECLSPEC_HIDDEN;
 void check_event_attr(HTMLDocumentNode*,nsIDOMHTMLElement*) DECLSPEC_HIDDEN;
+void init_event_target(EventTarget*) DECLSPEC_HIDDEN;
 void release_event_target(EventTarget*) DECLSPEC_HIDDEN;
 void fire_event(HTMLDocumentNode*,eventid_t,BOOL,HTMLDOMNode*,nsIDOMEvent*,IDispatch*) DECLSPEC_HIDDEN;
 HRESULT set_event_handler(EventTarget*,eventid_t,VARIANT*) DECLSPEC_HIDDEN;
diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c
index ab47323..2dfbeaa 100644
--- a/dlls/mshtml/htmlnode.c
+++ b/dlls/mshtml/htmlnode.c
@@ -1214,6 +1214,7 @@ void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsno
     node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
 
     ccref_init(&node->ccref, 1);
+    init_event_target(&node->event_target);
 
     if(&doc->node != node)
         htmldoc_addref(&doc->basedoc);
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index e3f22cf..a5db035 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -3020,6 +3020,7 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon,
     window->base.outer_window = outer_window;
     window->base.inner_window = window;
 
+    init_event_target(&window->event_target);
     init_dispex(&window->event_target.dispex, (IUnknown*)&window->base.IHTMLWindow2_iface, &HTMLWindow_dispex);
 
     window->task_magic = get_task_target_magic();
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 457e32b..89f2fcb 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -72,7 +72,6 @@
 typedef struct HTMLDOMNode HTMLDOMNode;
 typedef struct ConnectionPoint ConnectionPoint;
 typedef struct BSCallback BSCallback;
-typedef struct event_target_t event_target_t;
 typedef struct EventTarget EventTarget;
 
 #define TID_LIST \
@@ -366,7 +365,7 @@ typedef struct {
 
 struct EventTarget {
     DispatchEx dispex;
-    event_target_t *ptr;
+    struct wine_rb_tree handler_map;
 };
 
 typedef struct {
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c
index 51e2445..ab14c54 100644
--- a/dlls/mshtml/xmlhttprequest.c
+++ b/dlls/mshtml/xmlhttprequest.c
@@ -851,6 +851,7 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor
     ret->nsxhr = nsxhr;
 
     ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
+    init_event_target(&ret->event_target);
     init_dispex(&ret->event_target.dispex, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
             &HTMLXMLHttpRequest_dispex);
     ret->ref = 1;




More information about the wine-cvs mailing list