瀏覽代碼

LibWeb: Disentangle associated MessagePorts when a document is destroyed

Timothy Flynn 9 月之前
父節點
當前提交
ba1b26cdc2

+ 12 - 2
Userland/Libraries/LibWeb/DOM/Document.cpp

@@ -96,6 +96,7 @@
 #include <LibWeb/HTML/ListOfAvailableImages.h>
 #include <LibWeb/HTML/ListOfAvailableImages.h>
 #include <LibWeb/HTML/Location.h>
 #include <LibWeb/HTML/Location.h>
 #include <LibWeb/HTML/MessageEvent.h>
 #include <LibWeb/HTML/MessageEvent.h>
+#include <LibWeb/HTML/MessagePort.h>
 #include <LibWeb/HTML/Navigable.h>
 #include <LibWeb/HTML/Navigable.h>
 #include <LibWeb/HTML/Navigation.h>
 #include <LibWeb/HTML/Navigation.h>
 #include <LibWeb/HTML/NavigationParams.h>
 #include <LibWeb/HTML/NavigationParams.h>
@@ -3316,8 +3317,17 @@ void Document::destroy()
     // 3. Set document's salvageable state to false.
     // 3. Set document's salvageable state to false.
     m_salvageable = 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.
     // 6. Run any unloading document cleanup steps for document that are defined by this specification and other applicable specifications.
     run_unloading_cleanup_steps();
     run_unloading_cleanup_steps();

+ 14 - 0
Userland/Libraries/LibWeb/HTML/MessagePort.cpp

@@ -29,6 +29,12 @@ constexpr u8 IPC_FILE_TAG = 0xA5;
 
 
 JS_DEFINE_ALLOCATOR(MessagePort);
 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)
 JS::NonnullGCPtr<MessagePort> MessagePort::create(JS::Realm& realm)
 {
 {
     return realm.heap().allocate<MessagePort>(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)
 MessagePort::MessagePort(JS::Realm& realm)
     : DOM::EventTarget(realm)
     : DOM::EventTarget(realm)
 {
 {
+    all_message_ports().set(this);
 }
 }
 
 
 MessagePort::~MessagePort()
 MessagePort::~MessagePort()
 {
 {
+    all_message_ports().remove(this);
     disentangle();
     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)
 void MessagePort::initialize(JS::Realm& realm)
 {
 {
     Base::initialize(realm);
     Base::initialize(realm);

+ 4 - 1
Userland/Libraries/LibWeb/HTML/MessagePort.h

@@ -30,11 +30,15 @@ class MessagePort final : public DOM::EventTarget
 public:
 public:
     [[nodiscard]] static JS::NonnullGCPtr<MessagePort> create(JS::Realm&);
     [[nodiscard]] static JS::NonnullGCPtr<MessagePort> create(JS::Realm&);
 
 
+    static void for_each_message_port(Function<void(MessagePort&)>);
+
     virtual ~MessagePort() override;
     virtual ~MessagePort() override;
 
 
     // https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
     // https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
     void entangle_with(MessagePort&);
     void entangle_with(MessagePort&);
 
 
+    void disentangle();
+
     // https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage
     // 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);
     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;
     virtual void visit_edges(Cell::Visitor&) override;
 
 
     bool is_entangled() const { return static_cast<bool>(m_socket); }
     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);
     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&);
     void post_message_task_steps(SerializedTransferRecord&);