Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/HTML/MessagePort.cpp (C++)

Code before:

    // 3. If dataHolder.[[RemotePort]] is not null, then entangle dataHolder.[[RemotePort]] and value.
    //     (This will disentangle dataHolder.[[RemotePort]] from the original port that was transferred.)
    if (auto fd_tag = data_holder.decode<u8>(); fd_tag == IPC_FILE_TAG) {
        // TODO: Mach IPC
        auto fd = data_holder.decode<IPC::File>();
        m_transport = make<IPC::Transport>(MUST(Core::LocalSocket::adopt_fd(fd.take_fd())));

        m_transport->set_up_read_hook([strong_this = GC::make_root(this)]() {
            if (strong_this->m_enabled)
                strong_this->read_from_transport();
        });
    } else if (fd_tag != 0) {
        dbgln("Unexpected byte {:x} in MessagePort transfer data", fd_tag);
        VERIFY_NOT_REACHED();
    }

    return {};
}

void MessagePort::disentangle()
{
    if (auto remote_port = m_remote_port) {
        // Set the pointers to null before disentangling the remote port to prevent infinite recursion here.
        m_remote_port->m_remote_port = nullptr;
        m_remote_port = nullptr;

        if (remote_port)
            remote_port->disentangle();
    }

    if (m_transport) {
        m_transport->close_after_sending_all_pending_messages();
        m_transport.clear();
    }

    m_worker_event_target = nullptr;
}

// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
void MessagePort::entangle_with(MessagePort& remote_port)
{
    if (m_remote_port.ptr() == &remote_port)
        return;

    // 1. If one of the ports is already entangled, then disentangle it and the port that it was entangled with.
    if (is_entangled())
        disentangle();
    if (remote_port.is_entangled())
        remote_port.disentangle();


Review comment (suggestion):
This diff feels like it's out of sync with the commit message.

"Don't disentangle remote port when..." but then all the logic is *inside* `disentangle()` :thonk:

Code after:

    // 3. If dataHolder.[[RemotePort]] is not null, then entangle dataHolder.[[RemotePort]] and value.
    //     (This will disentangle dataHolder.[[RemotePort]] from the original port that was transferred.)
    if (auto fd_tag = data_holder.decode<u8>(); fd_tag == IPC_FILE_TAG) {
        // TODO: Mach IPC
        auto fd = data_holder.decode<IPC::File>();
        m_transport = make<IPC::Transport>(MUST(Core::LocalSocket::adopt_fd(fd.take_fd())));

        m_transport->set_up_read_hook([strong_this = GC::make_root(this)]() {
            if (strong_this->m_enabled)
                strong_this->read_from_transport();
        });
    } else if (fd_tag != 0) {
        dbgln("Unexpected byte {:x} in MessagePort transfer data", fd_tag);
        VERIFY_NOT_REACHED();
    }

    return {};
}

void MessagePort::disentangle()
{
    if (m_remote_port) {
        m_remote_port->m_remote_port = nullptr;
        m_remote_port = nullptr;
    }

    if (m_transport) {
        m_transport->close_after_sending_all_pending_messages();
        m_transport.clear();
    }

    m_worker_event_target = nullptr;
}

// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
void MessagePort::entangle_with(MessagePort& remote_port)
{
    if (m_remote_port.ptr() == &remote_port)
        return;

    // 1. If one of the ports is already entangled, then disentangle it and the port that it was entangled with.
    if (is_entangled())
        disentangle();
    if (remote_port.is_entangled())
        remote_port.disentangle();

    // 2. Associate the two ports to be entangled, so that they form the two parts of a new channel.
    //    (There is no MessageChannel object that represents this channel.)
    remote_port.m_remote_port = this;
    m_remote_port = &remote_port;