Repository: microsoft/terminal
File: src/cascadia/TerminalApp/DebugTapConnection.cpp (C++)

Code before:

using namespace ::winrt::Microsoft::Terminal::TerminalConnection;
using namespace ::winrt::Windows::Foundation;
namespace winrt::Microsoft::TerminalApp::implementation
{
    // DebugInputTapConnection is an implementation detail of DebugTapConnection.
    // It wraps the _actual_ connection so it can hook WriteInput and forward it
    // into the actual debug panel.
    class DebugInputTapConnection : public winrt::implements<DebugInputTapConnection, ITerminalConnection>
    {
    public:
        DebugInputTapConnection(winrt::com_ptr<DebugTapConnection> pairedTap, ITerminalConnection wrappedConnection) :
            _pairedTap{ pairedTap },
            _wrappedConnection{ std::move(wrappedConnection) }
        {
        }
        void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {}
        ~DebugInputTapConnection() = default;
        void Start()
        {
            _wrappedConnection.Start();
        }
        void WriteInput(hstring const& data)
        {
            _pairedTap->_PrintInput(data);
            _wrappedConnection.WriteInput(data);
        }
        void Resize(uint32_t rows, uint32_t columns) { _wrappedConnection.Resize(rows, columns); }
        void Close() { _wrappedConnection.Close(); }
        winrt::event_token TerminalOutput(TerminalOutputHandler const& args) { return _wrappedConnection.TerminalOutput(args); };
        void TerminalOutput(winrt::event_token const& token) noexcept { _wrappedConnection.TerminalOutput(token); };
        winrt::event_token StateChanged(TypedEventHandler<ITerminalConnection, IInspectable> const& handler) { return _wrappedConnection.StateChanged(handler); };
        void StateChanged(winrt::event_token const& token) noexcept { _wrappedConnection.StateChanged(token); };
        ConnectionState State() const noexcept { return _wrappedConnection.State(); }

    private:
        winrt::com_ptr<DebugTapConnection> _pairedTap;
        ITerminalConnection _wrappedConnection;
    };

    DebugTapConnection::DebugTapConnection(ITerminalConnection wrappedConnection)
    {
        _outputRevoker = wrappedConnection.TerminalOutput(winrt::auto_revoke, { this, &DebugTapConnection::_OutputHandler });
        _stateChangedRevoker = wrappedConnection.StateChanged(winrt::auto_revoke, [this](auto&& /*s*/, auto&& /*e*/) {
            _StateChangedHandlers(*this, nullptr);
        });
        _wrappedConnection = wrappedConnection;
    }

    DebugTapConnection::~DebugTapConnection()
    {

Review comment (performance):
Should we think about making it so that's not a problem? Should TermControl buffer so Connections (eventually, 3p connections) don't need to "slow down"?

Code after:

using namespace ::winrt::Microsoft::Terminal::TerminalConnection;
using namespace ::winrt::Windows::Foundation;
namespace winrt::Microsoft::TerminalApp::implementation
{
    // DebugInputTapConnection is an implementation detail of DebugTapConnection.
    // It wraps the _actual_ connection so it can hook WriteInput and forward it
    // into the actual debug panel.
    class DebugInputTapConnection : public winrt::implements<DebugInputTapConnection, ITerminalConnection>
    {
    public:
        DebugInputTapConnection(winrt::com_ptr<DebugTapConnection> pairedTap, ITerminalConnection wrappedConnection) :
            _pairedTap{ pairedTap },
            _wrappedConnection{ std::move(wrappedConnection) }
        {
        }
        void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {}
        ~DebugInputTapConnection() = default;
        winrt::fire_and_forget Start()
        {
            // GH#11282: It's possible that we're about to be started, _before_
            // our paired connection is started. Both will get Start()'ed when
            // their owning TermControl is finally laid out. However, if we're
            // started first, then we'll immediately start printing to the other
            // control as well, which might not have initialized yet. If we do
            // that, we'll explode.
            //
            // Instead, wait here until the other connection is started too,
            // before actually starting the connection to the client app. This
            // will ensure both controls are initialized before the client app
            // is.
            co_await winrt::resume_background();
            _pairedTap->_start.wait();

            _wrappedConnection.Start();
        }
        void WriteInput(hstring const& data)
        {
            _pairedTap->_PrintInput(data);
            _wrappedConnection.WriteInput(data);
        }
        void Resize(uint32_t rows, uint32_t columns) { _wrappedConnection.Resize(rows, columns); }
        void Close() { _wrappedConnection.Close(); }
        winrt::event_token TerminalOutput(TerminalOutputHandler const& args) { return _wrappedConnection.TerminalOutput(args); };
        void TerminalOutput(winrt::event_token const& token) noexcept { _wrappedConnection.TerminalOutput(token); };
        winrt::event_token StateChanged(TypedEventHandler<ITerminalConnection, IInspectable> const& handler) { return _wrappedConnection.StateChanged(handler); };
        void StateChanged(winrt::event_token const& token) noexcept { _wrappedConnection.StateChanged(token); };
        ConnectionState State() const noexcept { return _wrappedConnection.State(); }

    private:
        winrt::com_ptr<DebugTapConnection> _pairedTap;