Commit 51a68184 authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

mshtml: Add separate task list for tasks dispatching events.

They need to be handled separately because they are blocked by sync XHRs for the given window. Signed-off-by: 's avatarGabriel Ivăncescu <gabrielopcode@gmail.com>
parent 13d25529
......@@ -200,15 +200,14 @@ static inline HTMLStorage *impl_from_IHTMLStorage(IHTMLStorage *iface)
static HRESULT build_session_origin(IUri*,BSTR,BSTR*);
struct storage_event_task {
task_t header;
HTMLInnerWindow *window;
event_task_t header;
DOMEvent *event;
};
static void storage_event_proc(task_t *_task)
static void storage_event_proc(event_task_t *_task)
{
struct storage_event_task *task = (struct storage_event_task*)_task;
HTMLInnerWindow *window = task->window;
HTMLInnerWindow *window = task->header.window;
DOMEvent *event = task->event;
VARIANT_BOOL cancelled;
......@@ -221,11 +220,10 @@ static void storage_event_proc(task_t *_task)
}
}
static void storage_event_destr(task_t *_task)
static void storage_event_destr(event_task_t *_task)
{
struct storage_event_task *task = (struct storage_event_task*)_task;
IDOMEvent_Release(&task->event->IDOMEvent_iface);
IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
}
struct send_storage_event_ctx {
......@@ -254,9 +252,7 @@ static HRESULT push_storage_event_task(struct send_storage_event_ctx *ctx, HTMLI
}
task->event = event;
task->window = window;
IHTMLWindow2_AddRef(&task->window->base.IHTMLWindow2_iface);
return push_task(&task->header, storage_event_proc, storage_event_destr, window->task_magic);
return push_event_task(&task->header, window, storage_event_proc, storage_event_destr, window->task_magic);
}
static HRESULT send_storage_event_impl(struct send_storage_event_ctx *ctx, HTMLInnerWindow *window)
......
......@@ -2201,22 +2201,20 @@ static HRESULT WINAPI HTMLWindow6_get_maxConnectionsPerServer(IHTMLWindow6 *ifac
}
struct post_message_task {
task_t header;
HTMLInnerWindow *window;
event_task_t header;
DOMEvent *event;
} ;
};
static void post_message_proc(task_t *_task)
static void post_message_proc(event_task_t *_task)
{
struct post_message_task *task = (struct post_message_task *)_task;
dispatch_event(&task->window->event_target, task->event);
dispatch_event(&task->header.window->event_target, task->event);
}
static void post_message_destr(task_t *_task)
static void post_message_destr(event_task_t *_task)
{
struct post_message_task *task = (struct post_message_task *)_task;
IDOMEvent_Release(&task->event->IDOMEvent_iface);
IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
}
static HRESULT WINAPI HTMLWindow6_postMessage(IHTMLWindow6 *iface, BSTR msg, VARIANT targetOrigin)
......@@ -3297,9 +3295,7 @@ static HRESULT WINAPI window_private_postMessage(IWineHTMLWindowPrivate *iface,
}
task->event = event;
task->window = window;
IHTMLWindow2_AddRef(&task->window->base.IHTMLWindow2_iface);
return push_task(&task->header, post_message_proc, post_message_destr, window->task_magic);
return push_event_task(&task->header, window, post_message_proc, post_message_destr, window->task_magic);
}
dispatch_event(&window->event_target, event);
......
......@@ -1283,6 +1283,17 @@ struct task_t {
struct list entry;
};
typedef struct event_task_t event_task_t;
typedef void (*event_task_proc_t)(event_task_t*);
struct event_task_t {
LONG target_magic;
event_task_proc_t proc;
event_task_proc_t destr;
struct list entry;
HTMLInnerWindow *window;
};
typedef struct {
task_t header;
HTMLDocumentObj *doc;
......@@ -1291,6 +1302,7 @@ typedef struct {
typedef struct {
HWND thread_hwnd;
struct list task_list;
struct list event_task_list;
struct list timer_list;
struct wine_rb_tree session_storage_map;
} thread_data_t;
......@@ -1302,6 +1314,7 @@ void destroy_session_storage(thread_data_t*) DECLSPEC_HIDDEN;
LONG get_task_target_magic(void) DECLSPEC_HIDDEN;
HRESULT push_task(task_t*,task_proc_t,task_proc_t,LONG) DECLSPEC_HIDDEN;
HRESULT push_event_task(event_task_t*,HTMLInnerWindow*,event_task_proc_t,event_task_proc_t,LONG) DECLSPEC_HIDDEN;
void remove_target_tasks(LONG) DECLSPEC_HIDDEN;
ULONGLONG get_time_stamp(void) DECLSPEC_HIDDEN;
......
......@@ -455,21 +455,13 @@ static void notif_readystate(HTMLOuterWindow *window)
}
}
typedef struct {
task_t header;
HTMLOuterWindow *window;
} readystate_task_t;
static void notif_readystate_proc(task_t *_task)
static void notif_readystate_proc(event_task_t *task)
{
readystate_task_t *task = (readystate_task_t*)_task;
notif_readystate(task->window);
notif_readystate(task->window->base.outer_window);
}
static void notif_readystate_destr(task_t *_task)
static void notif_readystate_destr(event_task_t *task)
{
readystate_task_t *task = (readystate_task_t*)_task;
IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
}
void set_ready_state(HTMLOuterWindow *window, READYSTATE readystate)
......@@ -479,7 +471,7 @@ void set_ready_state(HTMLOuterWindow *window, READYSTATE readystate)
window->readystate = readystate;
if(window->readystate_locked) {
readystate_task_t *task;
event_task_t *task;
HRESULT hres;
if(window->readystate_pending || prev_state == readystate)
......@@ -489,10 +481,7 @@ void set_ready_state(HTMLOuterWindow *window, READYSTATE readystate)
if(!task)
return;
IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
task->window = window;
hres = push_task(&task->header, notif_readystate_proc, notif_readystate_destr, window->task_magic);
hres = push_event_task(task, window->base.inner_window, notif_readystate_proc, notif_readystate_destr, window->task_magic);
if(SUCCEEDED(hres))
window->readystate_pending = TRUE;
return;
......
......@@ -773,11 +773,11 @@ static void dispatch_script_readystatechange_event(HTMLScriptElement *script)
}
typedef struct {
task_t header;
event_task_t header;
HTMLScriptElement *elem;
} fire_readystatechange_task_t;
static void fire_readystatechange_proc(task_t *_task)
static void fire_readystatechange_proc(event_task_t *_task)
{
fire_readystatechange_task_t *task = (fire_readystatechange_task_t*)_task;
......@@ -788,7 +788,7 @@ static void fire_readystatechange_proc(task_t *_task)
dispatch_script_readystatechange_event(task->elem);
}
static void fire_readystatechange_task_destr(task_t *_task)
static void fire_readystatechange_task_destr(event_task_t *_task)
{
fire_readystatechange_task_t *task = (fire_readystatechange_task_t*)_task;
......@@ -818,8 +818,8 @@ static void set_script_elem_readystate(HTMLScriptElement *script_elem, READYSTAT
IHTMLScriptElement_AddRef(&script_elem->IHTMLScriptElement_iface);
task->elem = script_elem;
hres = push_task(&task->header, fire_readystatechange_proc, fire_readystatechange_task_destr,
script_elem->element.node.doc->window->task_magic);
hres = push_event_task(&task->header, script_elem->element.node.doc->window, fire_readystatechange_proc,
fire_readystatechange_task_destr, script_elem->element.node.doc->window->task_magic);
if(SUCCEEDED(hres))
script_elem->pending_readystatechange_event = TRUE;
}else {
......
......@@ -67,21 +67,33 @@ HRESULT push_task(task_t *task, task_proc_t proc, task_proc_t destr, LONG magic)
return S_OK;
}
static task_t *pop_task(void)
static void release_event_task(event_task_t *task)
{
task->destr(task);
IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
free(task);
}
HRESULT push_event_task(event_task_t *task, HTMLInnerWindow *window, event_task_proc_t proc, event_task_proc_t destr, LONG magic)
{
thread_data_t *thread_data;
task_t *task;
thread_data = get_thread_data(FALSE);
if(!thread_data)
return NULL;
task->target_magic = magic;
task->proc = proc;
task->destr = destr;
task->window = window;
IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
if(list_empty(&thread_data->task_list))
return NULL;
thread_data = get_thread_data(TRUE);
if(!thread_data) {
release_event_task(task);
return E_OUTOFMEMORY;
}
list_add_tail(&thread_data->event_task_list, &task->entry);
task = LIST_ENTRY(thread_data->task_list.next, task_t, entry);
list_remove(&task->entry);
return task;
PostMessageW(thread_data->thread_hwnd, WM_PROCESSTASK, 0, 0);
return S_OK;
}
static void release_task_timer(HWND thread_hwnd, task_timer_t *timer)
......@@ -124,6 +136,14 @@ void remove_target_tasks(LONG target)
free(task);
}
}
LIST_FOR_EACH_SAFE(liter, ltmp, &thread_data->event_task_list) {
event_task_t *task = LIST_ENTRY(liter, event_task_t, entry);
if(task->target_magic == target) {
list_remove(&task->entry);
release_event_task(task);
}
}
}
LONG get_task_target_magic(void)
......@@ -326,18 +346,37 @@ static LRESULT process_timer(void)
static LRESULT WINAPI hidden_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
thread_data_t *thread_data;
switch(msg) {
case WM_PROCESSTASK:
while(1) {
task_t *task = pop_task();
if(!task)
break;
thread_data = get_thread_data(FALSE);
if(!thread_data)
return 0;
task->proc(task);
task->destr(task);
free(task);
while(1) {
struct list *head = list_head(&thread_data->task_list);
if(head) {
task_t *task = LIST_ENTRY(head, task_t, entry);
list_remove(&task->entry);
task->proc(task);
task->destr(task);
free(task);
continue;
}
head = list_head(&thread_data->event_task_list);
if(head) {
event_task_t *task = LIST_ENTRY(head, event_task_t, entry);
list_remove(&task->entry);
task->proc(task);
release_event_task(task);
continue;
}
break;
}
return 0;
case WM_TIMER:
return process_timer();
......@@ -410,6 +449,7 @@ thread_data_t *get_thread_data(BOOL create)
TlsSetValue(mshtml_tls, thread_data);
list_init(&thread_data->task_list);
list_init(&thread_data->event_task_list);
list_init(&thread_data->timer_list);
wine_rb_init(&thread_data->session_storage_map, session_storage_map_cmp);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment