From 91c9bd9dcc23c4cc1a6ef6aabc89a1a50de34aa9 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Sun, 21 May 2023 18:34:00 -0700 Subject: [WebSocket] Implement `"nodebuffer"` binaryType --- src/bun.js/bindings/webcore/WebSocket.cpp | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'src/bun.js/bindings/webcore/WebSocket.cpp') diff --git a/src/bun.js/bindings/webcore/WebSocket.cpp b/src/bun.js/bindings/webcore/WebSocket.cpp index 404336050..4af556a7b 100644 --- a/src/bun.js/bindings/webcore/WebSocket.cpp +++ b/src/bun.js/bindings/webcore/WebSocket.cpp @@ -69,6 +69,8 @@ #include #include +#include "JSBuffer.h" + // #if USE(WEB_THREAD) // #include "WebCoreThreadRun.h" // #endif @@ -680,6 +682,8 @@ String WebSocket::binaryType() const // return "blob"_s; case BinaryType::ArrayBuffer: return "arraybuffer"_s; + case BinaryType::NodeBuffer: + return "nodebuffer"_s; } ASSERT_NOT_REACHED(); return String(); @@ -694,6 +698,9 @@ ExceptionOr WebSocket::setBinaryType(const String& binaryType) if (binaryType == "arraybuffer"_s) { m_binaryType = BinaryType::ArrayBuffer; return {}; + } else if (binaryType == "nodebuffer"_s) { + m_binaryType = BinaryType::NodeBuffer; + return {}; } // scriptExecutionContext()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "'" + binaryType + "' is not a valid value for binaryType; binaryType remains unchanged."); return Exception { SyntaxError, makeString("'"_s, binaryType, "' is not a valid value for binaryType; binaryType remains unchanged."_s) }; @@ -860,6 +867,49 @@ void WebSocket::didReceiveBinaryData(Vector&& binaryData) break; } + case BinaryType::NodeBuffer: { + + if (this->hasEventListeners("message"_s)) { + // the main reason for dispatching on a separate tick is to handle when you haven't yet attached an event listener + this->incPendingActivityCount(); + JSUint8Array* buffer = jsCast(JSValue::decode(JSBuffer__bufferFromLength(scriptExecutionContext()->jsGlobalObject(), binaryData.size()))); + if (binaryData.size() > 0) + memcpy(buffer->vector(), binaryData.data(), binaryData.size()); + JSC::EnsureStillAliveScope ensureStillAlive(buffer); + MessageEvent::Init init; + init.data = buffer; + init.origin = this->m_url.string(); + + dispatchEvent(MessageEvent::create(eventNames().messageEvent, WTFMove(init), EventIsTrusted::Yes)); + this->decPendingActivityCount(); + return; + } + + if (auto* context = scriptExecutionContext()) { + auto arrayBuffer = JSC::ArrayBuffer::tryCreate(binaryData.data(), binaryData.size()); + + this->incPendingActivityCount(); + + context->postTask([this, buffer = WTFMove(arrayBuffer), protectedThis = Ref { *this }](ScriptExecutionContext& context) { + ASSERT(scriptExecutionContext()); + size_t length = buffer->byteLength(); + JSUint8Array* uint8array = JSUint8Array::create( + scriptExecutionContext()->jsGlobalObject(), + reinterpret_cast(scriptExecutionContext()->jsGlobalObject())->JSBufferSubclassStructure(), + WTFMove(buffer.copyRef()), + 0, + length); + JSC::EnsureStillAliveScope ensureStillAlive(uint8array); + MessageEvent::Init init; + init.data = uint8array; + init.origin = protectedThis->m_url.string(); + protectedThis->dispatchEvent(MessageEvent::create(eventNames().messageEvent, WTFMove(init), EventIsTrusted::Yes)); + protectedThis->decPendingActivityCount(); + }); + } + + break; + } } // }); } -- cgit v1.2.3