From 51a68184914eeba4de6e0bb415885e8bcf47e05c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gabriel=20Iv=C4=83ncescu?= Date: Mon, 27 Feb 2023 16:02:13 +0200 Subject: [PATCH] mshtml: Add separate task list for tasks dispatching events. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit They need to be handled separately because they are blocked by sync XHRs for the given window. Signed-off-by: Gabriel Ivăncescu --- dlls/mshtml/htmlstorage.c | 14 +++----- dlls/mshtml/htmlwindow.c | 16 ++++------ dlls/mshtml/mshtml_private.h | 13 ++++++++ dlls/mshtml/persist.c | 21 +++--------- dlls/mshtml/script.c | 10 +++--- dlls/mshtml/task.c | 76 +++++++++++++++++++++++++++++++++----------- 6 files changed, 92 insertions(+), 58 deletions(-) diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 21e3df5c3fb..24eec4ba078 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -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) diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index ed497eacf4e..2d5db55c14d 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -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); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 1873799dbf9..6f0a4043115 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -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; diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index e527b3dc3c5..486643d8b21 100644 --- a/dlls/mshtml/persist.c +++ b/dlls/mshtml/persist.c @@ -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; diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index 8b1c1f11938..0e2241663dc 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -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 { diff --git a/dlls/mshtml/task.c b/dlls/mshtml/task.c index 34b6c711ddd..37667dcc9cc 100644 --- a/dlls/mshtml/task.c +++ b/dlls/mshtml/task.c @@ -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); } -- 2.11.4.GIT