LibWeb: Disentangle associated MessagePorts when a document is destroyed

This commit is contained in:
Timothy Flynn 2024-10-17 07:59:04 -04:00 committed by Tim Flynn
parent d44dd756b3
commit ba1b26cdc2
Notes: github-actions[bot] 2024-10-17 20:35:40 +00:00
3 changed files with 30 additions and 3 deletions

View file

@ -96,6 +96,7 @@
#include <LibWeb/HTML/ListOfAvailableImages.h>
#include <LibWeb/HTML/Location.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/MessagePort.h>
#include <LibWeb/HTML/Navigable.h>
#include <LibWeb/HTML/Navigation.h>
#include <LibWeb/HTML/NavigationParams.h>
@ -3316,8 +3317,17 @@ void Document::destroy()
// 3. Set document's salvageable state to false.
m_salvageable = false;
// FIXME: 4. Let ports be the list of MessagePorts whose relevant global object's associated Document is document.
// FIXME: 5. For each port in ports, disentangle port.
// 4. Let ports be the list of MessagePorts whose relevant global object's associated Document is document.
// 5. For each port in ports, disentangle port.
HTML::MessagePort::for_each_message_port([&](HTML::MessagePort& port) {
auto& global = HTML::relevant_global_object(port);
if (!is<HTML::Window>(global))
return;
auto& window = static_cast<HTML::Window&>(global);
if (&window.associated_document() == this)
port.disentangle();
});
// 6. Run any unloading document cleanup steps for document that are defined by this specification and other applicable specifications.
run_unloading_cleanup_steps();

View file

@ -29,6 +29,12 @@ constexpr u8 IPC_FILE_TAG = 0xA5;
JS_DEFINE_ALLOCATOR(MessagePort);
static HashTable<JS::RawGCPtr<MessagePort>>& all_message_ports()
{
static HashTable<JS::RawGCPtr<MessagePort>> ports;
return ports;
}
JS::NonnullGCPtr<MessagePort> MessagePort::create(JS::Realm& realm)
{
return realm.heap().allocate<MessagePort>(realm, realm);
@ -37,13 +43,21 @@ JS::NonnullGCPtr<MessagePort> MessagePort::create(JS::Realm& realm)
MessagePort::MessagePort(JS::Realm& realm)
: DOM::EventTarget(realm)
{
all_message_ports().set(this);
}
MessagePort::~MessagePort()
{
all_message_ports().remove(this);
disentangle();
}
void MessagePort::for_each_message_port(Function<void(MessagePort&)> callback)
{
for (auto port : all_message_ports())
callback(*port);
}
void MessagePort::initialize(JS::Realm& realm)
{
Base::initialize(realm);

View file

@ -30,11 +30,15 @@ class MessagePort final : public DOM::EventTarget
public:
[[nodiscard]] static JS::NonnullGCPtr<MessagePort> create(JS::Realm&);
static void for_each_message_port(Function<void(MessagePort&)>);
virtual ~MessagePort() override;
// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
void entangle_with(MessagePort&);
void disentangle();
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage
WebIDL::ExceptionOr<void> post_message(JS::Value message, Vector<JS::Handle<JS::Object>> const& transfer);
@ -66,7 +70,6 @@ private:
virtual void visit_edges(Cell::Visitor&) override;
bool is_entangled() const { return static_cast<bool>(m_socket); }
void disentangle();
WebIDL::ExceptionOr<void> message_port_post_message_steps(JS::GCPtr<MessagePort> target_port, JS::Value message, StructuredSerializeOptions const& options);
void post_message_task_steps(SerializedTransferRecord&);