mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 09:41:41 +00:00
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: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
parent
13d25529a3
commit
51a6818491
|
@ -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;
|
||||
}
|
||||
|
||||
task = LIST_ENTRY(thread_data->task_list.next, task_t, entry);
|
||||
list_remove(&task->entry);
|
||||
return task;
|
||||
list_add_tail(&thread_data->event_task_list, &task->entry);
|
||||
|
||||
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:
|
||||
thread_data = get_thread_data(FALSE);
|
||||
if(!thread_data)
|
||||
return 0;
|
||||
|
||||
while(1) {
|
||||
task_t *task = pop_task();
|
||||
if(!task)
|
||||
break;
|
||||
struct list *head = list_head(&thread_data->task_list);
|
||||
|
||||
task->proc(task);
|
||||
task->destr(task);
|
||||
free(task);
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue