mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
* Move uWebSockets and uSockets forks into Bun's repository * Update Makefile * Update settings.json * Update libuwsockets.cpp * Remove backends we won't be using * Update bindings.cpp --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
203 lines
7.4 KiB
C++
203 lines
7.4 KiB
C++
#include "root.h"
|
|
#include <bun-uws/src/App.h>
|
|
|
|
#include <JavaScriptCore/InspectorFrontendChannel.h>
|
|
#include <JavaScriptCore/JSGlobalObjectDebuggable.h>
|
|
#include <JavaScriptCore/JSGlobalObjectDebugger.h>
|
|
#include <JavaScriptCore/Debugger.h>
|
|
|
|
extern "C" void Bun__tickWhilePaused(bool*);
|
|
|
|
namespace Bun {
|
|
using namespace JSC;
|
|
template<bool isSSL>
|
|
class BunInspectorConnection : public Inspector::FrontendChannel {
|
|
public:
|
|
using BunInspectorSocket = uWS::WebSocket<isSSL, true, BunInspectorConnection*>;
|
|
|
|
BunInspectorConnection(BunInspectorSocket* ws, JSC::JSGlobalObject* globalObject)
|
|
: ws(ws)
|
|
, globalObject(globalObject)
|
|
, pendingMessages()
|
|
{
|
|
}
|
|
|
|
~BunInspectorConnection()
|
|
{
|
|
}
|
|
|
|
Inspector::FrontendChannel::ConnectionType connectionType() const override
|
|
{
|
|
return Inspector::FrontendChannel::ConnectionType::Remote;
|
|
}
|
|
|
|
void onOpen(JSC::JSGlobalObject* globalObject)
|
|
{
|
|
this->globalObject = globalObject;
|
|
this->globalObject->inspectorDebuggable().connect(*this);
|
|
|
|
Inspector::JSGlobalObjectDebugger* debugger = reinterpret_cast<Inspector::JSGlobalObjectDebugger*>(this->globalObject->debugger());
|
|
if (debugger) {
|
|
debugger->runWhilePausedCallback = [](JSC::JSGlobalObject& globalObject, bool& isPaused) -> void {
|
|
Bun__tickWhilePaused(&isPaused);
|
|
};
|
|
}
|
|
}
|
|
|
|
void onClose()
|
|
{
|
|
this->globalObject->inspectorDebuggable().disconnect(*this);
|
|
this->pendingMessages.clear();
|
|
}
|
|
|
|
void sendMessageToFrontend(const String& message) override
|
|
{
|
|
send(message);
|
|
}
|
|
|
|
void send(const WTF::String& message)
|
|
{
|
|
if (ws->getBufferedAmount() == 0) {
|
|
WTF::CString messageCString = message.utf8();
|
|
ws->send(std::string_view { messageCString.data(), messageCString.length() }, uWS::OpCode::TEXT);
|
|
} else {
|
|
pendingMessages.append(message);
|
|
}
|
|
}
|
|
|
|
void onMessage(std::string_view message)
|
|
{
|
|
WTF::String messageString = WTF::String::fromUTF8(message.data(), message.length());
|
|
Inspector::JSGlobalObjectDebugger* debugger = reinterpret_cast<Inspector::JSGlobalObjectDebugger*>(this->globalObject->debugger());
|
|
if (debugger) {
|
|
debugger->runWhilePausedCallback = [](JSC::JSGlobalObject& globalObject, bool& done) -> void {
|
|
Inspector::JSGlobalObjectDebugger* debugger = reinterpret_cast<Inspector::JSGlobalObjectDebugger*>(globalObject.debugger());
|
|
Bun__tickWhilePaused(&done);
|
|
};
|
|
}
|
|
this->globalObject->inspectorDebuggable().dispatchMessageFromRemote(WTFMove(messageString));
|
|
}
|
|
|
|
void drain()
|
|
{
|
|
if (pendingMessages.size() == 0)
|
|
return;
|
|
|
|
if (ws->getBufferedAmount() == 0) {
|
|
ws->cork([&]() {
|
|
for (auto& message : pendingMessages) {
|
|
WTF::CString messageCString = message.utf8();
|
|
ws->send(std::string_view { messageCString.data(), messageCString.length() }, uWS::OpCode::TEXT);
|
|
}
|
|
pendingMessages.clear();
|
|
});
|
|
}
|
|
}
|
|
|
|
WTF::Vector<WTF::String> pendingMessages;
|
|
JSC::JSGlobalObject* globalObject;
|
|
BunInspectorSocket* ws;
|
|
};
|
|
|
|
using BunInspectorConnectionNoSSL = BunInspectorConnection<false>;
|
|
using SSLBunInspectorConnection = BunInspectorConnection<true>;
|
|
|
|
template<bool isSSL>
|
|
static void addInspector(void* app, JSC::JSGlobalObject* globalObject)
|
|
{
|
|
if constexpr (isSSL) {
|
|
auto handler = uWS::SSLApp::WebSocketBehavior<SSLBunInspectorConnection*> {
|
|
/* Settings */
|
|
.compression = uWS::DISABLED,
|
|
.maxPayloadLength = 16 * 1024 * 1024,
|
|
.idleTimeout = 960,
|
|
.maxBackpressure = 16 * 1024 * 1024,
|
|
.closeOnBackpressureLimit = false,
|
|
.resetIdleTimeoutOnSend = true,
|
|
.sendPingsAutomatically = true,
|
|
/* Handlers */
|
|
.upgrade = nullptr,
|
|
.open = [globalObject](auto* ws) {
|
|
globalObject->setInspectable(true);
|
|
*ws->getUserData() = new SSLBunInspectorConnection(ws, globalObject);
|
|
SSLBunInspectorConnection* inspector = *ws->getUserData();
|
|
inspector->onOpen(globalObject);
|
|
//
|
|
},
|
|
.message = [](auto* ws, std::string_view message, uWS::OpCode opCode) {
|
|
SSLBunInspectorConnection* inspector = *(SSLBunInspectorConnection**)ws->getUserData();
|
|
inspector->onMessage(message);
|
|
//
|
|
},
|
|
.drain = [](auto* ws) {
|
|
SSLBunInspectorConnection* inspector = *(SSLBunInspectorConnection**)ws->getUserData();
|
|
inspector->drain();
|
|
//
|
|
},
|
|
.ping = [](auto* /*ws*/, std::string_view) {
|
|
/* Not implemented yet */ },
|
|
.pong = [](auto* /*ws*/, std::string_view) {
|
|
/* Not implemented yet */ },
|
|
|
|
.close = [](auto* ws, int /*code*/, std::string_view /*message*/) {
|
|
SSLBunInspectorConnection* inspector = *(SSLBunInspectorConnection**)ws->getUserData();
|
|
inspector->onClose();
|
|
delete inspector; }
|
|
};
|
|
|
|
((uWS::SSLApp*)app)->ws<SSLBunInspectorConnection*>("/bun:inspect", std::move(handler));
|
|
} else {
|
|
|
|
auto handler = uWS::App::WebSocketBehavior<BunInspectorConnectionNoSSL*> {
|
|
/* Settings */
|
|
.compression = uWS::DISABLED,
|
|
.maxPayloadLength = 16 * 1024 * 1024,
|
|
.idleTimeout = 960,
|
|
.maxBackpressure = 16 * 1024 * 1024,
|
|
.closeOnBackpressureLimit = false,
|
|
.resetIdleTimeoutOnSend = true,
|
|
.sendPingsAutomatically = true,
|
|
/* Handlers */
|
|
.upgrade = nullptr,
|
|
.open = [globalObject](auto* ws) {
|
|
globalObject->setInspectable(true);
|
|
*ws->getUserData() = new BunInspectorConnectionNoSSL(ws, globalObject);
|
|
BunInspectorConnectionNoSSL* inspector = *ws->getUserData();
|
|
inspector->onOpen(globalObject);
|
|
//
|
|
},
|
|
.message = [](auto* ws, std::string_view message, uWS::OpCode opCode) {
|
|
BunInspectorConnectionNoSSL* inspector = *(BunInspectorConnectionNoSSL**)ws->getUserData();
|
|
inspector->onMessage(message);
|
|
//
|
|
},
|
|
.drain = [](auto* ws) {
|
|
BunInspectorConnectionNoSSL* inspector = *(BunInspectorConnectionNoSSL**)ws->getUserData();
|
|
inspector->drain();
|
|
//
|
|
},
|
|
.ping = [](auto* /*ws*/, std::string_view) {
|
|
/* Not implemented yet */ },
|
|
.pong = [](auto* /*ws*/, std::string_view) {
|
|
/* Not implemented yet */ },
|
|
|
|
.close = [](auto* ws, int /*code*/, std::string_view /*message*/) {
|
|
BunInspectorConnectionNoSSL* inspector = *(BunInspectorConnectionNoSSL**)ws->getUserData();
|
|
inspector->onClose();
|
|
delete inspector; }
|
|
};
|
|
|
|
((uWS::App*)app)->ws<BunInspectorConnectionNoSSL*>("/bun:inspect", std::move(handler));
|
|
}
|
|
}
|
|
|
|
extern "C" void Bun__addInspector(bool isSSL, void* app, JSC::JSGlobalObject* globalObject)
|
|
{
|
|
if (isSSL) {
|
|
addInspector<true>((uWS::TemplatedApp<true>*)app, globalObject);
|
|
} else {
|
|
addInspector<false>((uWS::TemplatedApp<false>*)app, globalObject);
|
|
}
|
|
};
|
|
}
|