From fd8d350b4756817598ee49a11b9efc3b953dbb00 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Sun, 6 Oct 2024 22:41:11 +0100 Subject: [PATCH] LibWeb: Don't discard PostedMessage tasks when closing a worker The spec expects `postMessage()` to act as if it is invoked immediately. Since `postMessage()` isn't actually invoked immediately, keep tasks with source `PostedMessage` in the task queue, so that these tasks are processed. Fixes a hang when `WorkerGlobalScope.close()` is called immediately after `postMessage()`. --- Tests/LibWeb/TestConfig.ini | 1 + .../Worker/Worker-close-after-postMessage.txt | 1 + .../input/Worker/Worker-close-after-postMessage.html | 12 ++++++++++++ .../input/Worker/worker-close-after-postMessage.js | 4 ++++ Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp | 5 +++-- 5 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/Worker/Worker-close-after-postMessage.txt create mode 100644 Tests/LibWeb/Text/input/Worker/Worker-close-after-postMessage.html create mode 100644 Tests/LibWeb/Text/input/Worker/worker-close-after-postMessage.js diff --git a/Tests/LibWeb/TestConfig.ini b/Tests/LibWeb/TestConfig.ini index 706176ea153..7934065a55c 100644 --- a/Tests/LibWeb/TestConfig.ini +++ b/Tests/LibWeb/TestConfig.ini @@ -4,6 +4,7 @@ Text/input/Crypto/SubtleCrypto-exportKey.html Text/input/Crypto/SubtleCrypto-generateKey.html Text/input/WebAnimations/misc/DocumentTimeline.html Text/input/Worker/Worker-blob.html +Text/input/Worker/Worker-close-after-postMessage.html Text/input/Worker/Worker-crypto.html Text/input/Worker/Worker-echo.html Text/input/Worker/Worker-importScripts.html diff --git a/Tests/LibWeb/Text/expected/Worker/Worker-close-after-postMessage.txt b/Tests/LibWeb/Text/expected/Worker/Worker-close-after-postMessage.txt new file mode 100644 index 00000000000..88615149d25 --- /dev/null +++ b/Tests/LibWeb/Text/expected/Worker/Worker-close-after-postMessage.txt @@ -0,0 +1 @@ +PASS (didn't hang) \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/Worker/Worker-close-after-postMessage.html b/Tests/LibWeb/Text/input/Worker/Worker-close-after-postMessage.html new file mode 100644 index 00000000000..8f9f5565337 --- /dev/null +++ b/Tests/LibWeb/Text/input/Worker/Worker-close-after-postMessage.html @@ -0,0 +1,12 @@ + + + diff --git a/Tests/LibWeb/Text/input/Worker/worker-close-after-postMessage.js b/Tests/LibWeb/Text/input/Worker/worker-close-after-postMessage.js new file mode 100644 index 00000000000..be1eff4f80d --- /dev/null +++ b/Tests/LibWeb/Text/input/Worker/worker-close-after-postMessage.js @@ -0,0 +1,4 @@ +self.onmessage = function () { + postMessage("PASS (didn't hang)"); + self.close(); +}; diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp index de2a8fbe1cd..0145165712d 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp @@ -68,8 +68,9 @@ void WorkerGlobalScope::set_internal_port(JS::NonnullGCPtr port) void WorkerGlobalScope::close_a_worker() { // 1. Discard any tasks that have been added to workerGlobal's relevant agent's event loop's task queues. - relevant_settings_object(*this).responsible_event_loop().task_queue().remove_tasks_matching([](HTML::Task const&) { - return true; + relevant_settings_object(*this).responsible_event_loop().task_queue().remove_tasks_matching([](HTML::Task const& task) { + // NOTE: We don't discard tasks with the PostedMessage source, as the spec expects PostMessage() to act as if it is invoked immediately + return task.source() != HTML::Task::Source::PostedMessage; }); // 2. Set workerGlobal's closing flag to true. (This prevents any further tasks from being queued.)