WebSocket is a global

This commit is contained in:
Jarred Sumner
2022-06-17 23:18:18 -07:00
committed by Jarred Sumner
parent 71025c8bcc
commit be9efacf1b
23 changed files with 353 additions and 269 deletions

View File

@@ -10,7 +10,6 @@ class GlobalObject;
#include "headers-handwritten.h"
#include "BunClientData.h"
#include "WebCoreJSBuiltinInternals.h"
#include "JavaScriptCore/CallFrame.h"
namespace JSC {

View File

@@ -1,62 +1,129 @@
#include "root.h"
#include "headers.h"
#include "ScriptExecutionContext.h"
#include "webcore/WebSocket.h"
#include <uws/src/App.h>
#include "WebSocketStream.h"
extern "C" void Bun__startLoop(us_loop_t* loop);
namespace WebCore {
template<bool isSSL>
us_socket_context_t* ScriptExecutionContext::webSocketContext()
template<bool SSL, bool isServer>
static void registerHTTPContextForWebSocket(ScriptExecutionContext* script, us_socket_context_t* ctx, us_loop_t* loop)
{
if constexpr (isSSL) {
if (!m_ssl_client_websockets_ctx) {
us_loop_t* loop = (us_loop_t*)uWS::Loop::get();
us_socket_context_options_t opts;
memset(&opts, 0, sizeof(us_socket_context_options_t));
this->m_ssl_client_websockets_ctx = us_create_socket_context(1, loop, sizeof(size_t), opts);
void** ptr = reinterpret_cast<void**>(us_socket_context_ext(1, m_ssl_client_websockets_ctx));
*ptr = this;
registerHTTPContextForWebSocket<isSSL, false>(this, m_ssl_client_websockets_ctx);
if constexpr (!isServer) {
if constexpr (SSL) {
Bun__WebSocketHTTPSClient__register(script->jsGlobalObject(), loop, ctx);
} else {
Bun__WebSocketHTTPClient__register(script->jsGlobalObject(), loop, ctx);
}
return m_ssl_client_websockets_ctx;
} else {
if (!m_client_websockets_ctx) {
us_loop_t* loop = (us_loop_t*)uWS::Loop::get();
us_socket_context_options_t opts;
memset(&opts, 0, sizeof(us_socket_context_options_t));
this->m_client_websockets_ctx = us_create_socket_context(0, loop, sizeof(size_t), opts);
void** ptr = reinterpret_cast<void**>(us_socket_context_ext(0, m_client_websockets_ctx));
*ptr = this;
registerHTTPContextForWebSocket<isSSL, false>(this, m_client_websockets_ctx);
}
return m_client_websockets_ctx;
RELEASE_ASSERT_NOT_REACHED();
}
}
template<bool isSSL, bool isServer>
uWS::WebSocketContext<isSSL, isServer, ScriptExecutionContext*>* ScriptExecutionContext::connnectedWebSocketContext()
us_socket_context_t* ScriptExecutionContext::webSocketContextSSL()
{
if constexpr (isSSL) {
if (!m_connected_ssl_client_websockets_ctx) {
// should be the parent
RELEASE_ASSERT(m_ssl_client_websockets_ctx);
m_connected_client_websockets_ctx = registerWebSocketClientContext(this, webSocketContext<isSSL>());
}
return m_connected_ssl_client_websockets_ctx;
} else {
if (!m_connected_client_websockets_ctx) {
// should be the parent
RELEASE_ASSERT(m_client_websockets_ctx);
m_connected_client_websockets_ctx = registerWebSocketClientContext(this, webSocketContext<isSSL>());
}
return m_connected_client_websockets_ctx;
if (!m_ssl_client_websockets_ctx) {
us_loop_t* loop = (us_loop_t*)uWS::Loop::get();
us_socket_context_options_t opts;
memset(&opts, 0, sizeof(us_socket_context_options_t));
this->m_ssl_client_websockets_ctx = us_create_socket_context(1, loop, sizeof(size_t), opts);
void** ptr = reinterpret_cast<void**>(us_socket_context_ext(1, m_ssl_client_websockets_ctx));
*ptr = this;
registerHTTPContextForWebSocket<true, false>(this, m_ssl_client_websockets_ctx, loop);
}
return m_ssl_client_websockets_ctx;
}
us_socket_context_t* ScriptExecutionContext::webSocketContextNoSSL()
{
if (!m_client_websockets_ctx) {
us_loop_t* loop = (us_loop_t*)uWS::Loop::get();
us_socket_context_options_t opts;
memset(&opts, 0, sizeof(us_socket_context_options_t));
this->m_client_websockets_ctx = us_create_socket_context(0, loop, sizeof(size_t), opts);
void** ptr = reinterpret_cast<void**>(us_socket_context_ext(0, m_client_websockets_ctx));
*ptr = this;
registerHTTPContextForWebSocket<false, false>(this, m_client_websockets_ctx, loop);
}
return m_client_websockets_ctx;
}
template<bool SSL>
static uWS::WebSocketContext<SSL, false, WebCore::WebSocket*>* registerWebSocketClientContext(ScriptExecutionContext* script, us_socket_context_t* parent)
{
uWS::Loop* loop = uWS::Loop::get();
uWS::WebSocketContext<SSL, false, WebCore::WebSocket*>* ctx = uWS::WebSocketContext<SSL, false, WebCore::WebSocket*>::createClient(loop, parent);
auto* opts = ctx->getExt();
/* Maximum message size we can receive */
static unsigned int maxPayloadLength = 128 * 1024 * 1024;
/* 2 minutes timeout is good */
static unsigned short idleTimeout = 120;
/* 64kb backpressure is probably good */
static unsigned int maxBackpressure = 128 * 1024 * 1024;
static bool closeOnBackpressureLimit = false;
/* This one depends on kernel timeouts and is a bad default */
static bool resetIdleTimeoutOnSend = false;
/* A good default, esp. for newcomers */
static bool sendPingsAutomatically = true;
/* Maximum socket lifetime in seconds before forced closure (defaults to disabled) */
static unsigned short maxLifetime = 0;
opts->maxPayloadLength = maxPayloadLength;
opts->maxBackpressure = maxBackpressure;
opts->closeOnBackpressureLimit = closeOnBackpressureLimit;
opts->resetIdleTimeoutOnSend = resetIdleTimeoutOnSend;
opts->sendPingsAutomatically = sendPingsAutomatically;
// opts->compression = compression;
// TODO:
opts->compression = uWS::CompressOptions::DISABLED;
opts->openHandler = [](uWS::WebSocket<SSL, false, WebCore::WebSocket*>* ws) {
WebCore::WebSocket* webSocket = *ws->getUserData();
webSocket->didConnect();
};
opts->messageHandler = [](uWS::WebSocket<SSL, false, WebCore::WebSocket*>* ws, std::string_view input, uWS::OpCode opCode) {
WebCore::WebSocket* webSocket = *ws->getUserData();
if (opCode == uWS::OpCode::BINARY) {
webSocket->didReceiveBinaryData({ const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(input.data())), input.length() });
} else {
webSocket->didReceiveMessage(WTF::String::fromUTF8(input.data(), input.length()));
}
};
// pts->drainHandler = [](uWS::WebSocket<SSL, false, WebCore::WebSocket>* ws, std::string_view input, uWS::OpCode opCode) {
// WebCore::WebSocket* webSocket = *ws->getUserData();
// webSocket->didReceiveData(input.data(), input.length());
// };
opts->closeHandler = [](uWS::WebSocket<SSL, false, WebCore::WebSocket*>* ws, int code, std::string_view message) {
WebCore::WebSocket* webSocket = *ws->getUserData();
webSocket->didClose(
ws->getBufferedAmount(),
code,
WTF::String::fromUTF8(
message.data(),
message.length()));
};
return ctx;
}
uWS::WebSocketContext<false, false, WebSocket*>* ScriptExecutionContext::connectedWebSocketKindClient()
{
return registerWebSocketClientContext<false>(this, webSocketContextNoSSL());
}
uWS::WebSocketContext<true, false, WebSocket*>* ScriptExecutionContext::connectedWebSocketKindClientSSL()
{
return registerWebSocketClientContext<true>(this, webSocketContextSSL());
}
}

View File

@@ -14,20 +14,18 @@
namespace uWS {
template<bool isServer, bool isClient, typename UserData>
struct WebSocketContext;
}
struct us_socket_t;
struct us_socket_context_t;
struct us_loop_t;
namespace WebCore {
class ScriptExecutionContext : public CanMakeWeakPtr<ScriptExecutionContext> {
class WebSocket;
class ScriptExecutionContext : public CanMakeWeakPtr<ScriptExecutionContext> {
public:
ScriptExecutionContext(JSC::VM* vm, JSC::JSGlobalObject* globalObject)
: m_vm(vm)
, m_globalObject(globalObject)
{
}
class Task {
WTF_MAKE_FAST_ALLOCATED;
@@ -62,16 +60,27 @@ public:
bool m_isCleanupTask;
};
public:
ScriptExecutionContext(JSC::VM* vm, JSC::JSGlobalObject* globalObject)
: m_vm(vm)
, m_globalObject(globalObject)
{
}
JSC::JSGlobalObject* jsGlobalObject()
{
return m_globalObject;
}
template<bool isSSL>
us_socket_context_t* webSocketContext();
template<bool isSSL, bool isServer>
uWS::WebSocketContext<isSSL, isServer, ScriptExecutionContext*>* connnectedWebSocketContext();
us_socket_context_t* webSocketContext()
{
if constexpr (isSSL) {
return this->webSocketContextSSL();
} else {
return this->webSocketContextNoSSL();
}
}
const WTF::URL& url() const { return m_url; }
bool activeDOMObjectsAreSuspended() { return false; }
@@ -107,10 +116,34 @@ private:
JSC::JSGlobalObject* m_globalObject = nullptr;
WTF::URL m_url = WTF::URL();
us_socket_context_t* webSocketContextSSL();
us_socket_context_t* webSocketContextNoSSL();
uWS::WebSocketContext<true, false, WebSocket*>* connectedWebSocketKindClientSSL();
uWS::WebSocketContext<false, false, WebSocket*>* connectedWebSocketKindClient();
us_socket_context_t* m_ssl_client_websockets_ctx = nullptr;
us_socket_context_t* m_client_websockets_ctx = nullptr;
uWS::WebSocketContext<true, false, ScriptExecutionContext*>* m_connected_ssl_client_websockets_ctx = nullptr;
uWS::WebSocketContext<true, true, ScriptExecutionContext*>* m_connected_client_websockets_ctx = nullptr;
uWS::WebSocketContext<true, false, WebSocket*>* m_connected_ssl_client_websockets_ctx = nullptr;
uWS::WebSocketContext<false, false, WebSocket*>* m_connected_client_websockets_ctx = nullptr;
public:
template<bool isSSL, bool isServer>
uWS::WebSocketContext<isSSL, isServer, WebSocket*>* connnectedWebSocketContext()
{
if constexpr (isSSL) {
if (!m_connected_ssl_client_websockets_ctx) {
m_connected_ssl_client_websockets_ctx = connectedWebSocketKindClientSSL();
}
return m_connected_ssl_client_websockets_ctx;
} else {
if (!m_connected_client_websockets_ctx) {
m_connected_client_websockets_ctx = connectedWebSocketKindClient();
}
return m_connected_client_websockets_ctx;
}
}
};
}

View File

@@ -1,5 +1,7 @@
//clang-format off
namespace Zig { class GlobalObject; }
namespace Zig {
class GlobalObject;
}
/*
* Copyright (c) 2015 Igalia
* Copyright (c) 2015 Igalia S.L.
@@ -8,7 +10,7 @@ namespace Zig { class GlobalObject; }
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
* Copyright (c) 2022 Codeblog Corp. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +19,7 @@ namespace Zig { class GlobalObject; }
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -29,7 +31,7 @@ namespace Zig { class GlobalObject; }
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*
*/
// DO NOT EDIT THIS FILE. It is automatically generated from JavaScript files for

View File

@@ -1,4 +1,5 @@
#include "root.h"
#include "ZigGlobalObject.h"
#include "helpers.h"
@@ -135,6 +136,8 @@ using JSBuffer = WebCore::JSBuffer;
#include "JavaScriptCore/BuiltinNames.h"
#include "JSTextEncoder.h"
#include "StructuredClone.h"
#include "JSWebSocket.h"
#include "JSMessageEvent.h"
#include "ReadableStream.h"
#include "JSSink.h"
@@ -453,6 +456,28 @@ JSC_DEFINE_CUSTOM_GETTER(JSCloseEvent_getter,
WebCore::JSCloseEvent::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject));
}
JSC_DECLARE_CUSTOM_GETTER(JSMessageEvent_getter);
JSC_DEFINE_CUSTOM_GETTER(JSMessageEvent_getter,
(JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
JSC::PropertyName))
{
Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject);
return JSC::JSValue::encode(
WebCore::JSMessageEvent::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject));
}
JSC_DECLARE_CUSTOM_GETTER(JSWebSocket_getter);
JSC_DEFINE_CUSTOM_GETTER(JSWebSocket_getter,
(JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
JSC::PropertyName))
{
Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject);
return JSC::JSValue::encode(
WebCore::JSWebSocket::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject));
}
JSC_DECLARE_CUSTOM_GETTER(JSEvent_getter);
JSC_DEFINE_CUSTOM_GETTER(JSEvent_getter,
@@ -1872,6 +1897,12 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm)
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "CloseEvent"_s), JSC::CustomGetterSetter::create(vm, JSCloseEvent_getter, nullptr),
JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "MessageEvent"_s), JSC::CustomGetterSetter::create(vm, JSMessageEvent_getter, nullptr),
JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "WebSocket"_s), JSC::CustomGetterSetter::create(vm, JSWebSocket_getter, nullptr),
JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Buffer"_s), JSC::CustomGetterSetter::create(vm, JSBuffer_getter, nullptr),
JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "TextEncoder"_s), JSC::CustomGetterSetter::create(vm, JSTextEncoder_getter, nullptr),

View File

@@ -186,6 +186,10 @@ pub const JSReadableStreamFile = JSC.WebCore.FileBlobLoader.Source.JSReadableStr
// Sinks
pub const JSArrayBufferSink = JSC.WebCore.ArrayBufferSink.JSSink;
// WebSocket
pub const WebSocketHTTPClient = @import("../../../http/websocket_http_client.zig").WebSocketHTTPClient;
pub const WebSocketHTTSPClient = @import("../../../http/websocket_http_client.zig").WebSocketHTTPSClient;
pub fn Errorable(comptime Type: type) type {
return extern struct {
result: Result,
@@ -2504,6 +2508,9 @@ pub const BunTimer = Bun.Timer;
pub const Formatter = ZigConsoleClient.Formatter;
comptime {
WebSocketHTTPClient.shim.ref();
WebSocketHTTSPClient.shim.ref();
if (!is_bindgen) {
_ = Process.getTitle;
_ = Process.setTitle;

View File

@@ -1,4 +1,4 @@
//-- AUTOGENERATED FILE -- 1655351052
//-- AUTOGENERATED FILE -- 1655526456
// clang-format off
#pragma once

View File

@@ -187,6 +187,9 @@ typedef struct StringPointer {
} StringPointer;
#endif
typedef void WebSocketHTTPClient;
typedef void WebSocketHTTPSClient;
#ifdef __cplusplus
extern "C" ZigErrorCode Zig_ErrorCodeParserError;

View File

@@ -65,3 +65,6 @@ pub const struct_WebCore__FetchHeaders = bindings.FetchHeaders;
pub const StringPointer = @import("../../../api/schema.zig").Api.StringPointer;
pub const struct_VirtualMachine = bindings.VirtualMachine;
pub const ArrayBufferSink = @import("../webcore/streams.zig").ArrayBufferSink;
pub const WebSocketHTTPClient = bindings.WebSocketHTTPClient;
pub const WebSocketHTTPSClient = bindings.WebSocketHTTPSClient;

View File

@@ -1,5 +1,5 @@
// clang-format: off
//-- AUTOGENERATED FILE -- 1655351052
//-- AUTOGENERATED FILE -- 1655526456
#pragma once
#include <stddef.h>
@@ -137,6 +137,7 @@ typedef bJSC__Identifier JSC__Identifier; // JSC::Identifier
typedef struct JSC__ArrayPrototype JSC__ArrayPrototype; // JSC::ArrayPrototype
typedef struct Zig__JSMicrotaskCallback Zig__JSMicrotaskCallback; // Zig::JSMicrotaskCallback
typedef bJSC__JSPromise JSC__JSPromise; // JSC::JSPromise
typedef WebSocketHTTPClient WebSocketHTTPClient;
typedef struct JSC__SetIteratorPrototype JSC__SetIteratorPrototype; // JSC::SetIteratorPrototype
typedef SystemError SystemError;
typedef bJSC__JSCell JSC__JSCell; // JSC::JSCell
@@ -155,6 +156,7 @@ typedef struct JSC__CallFrame JSC__CallFrame; // JSC::CallFrame
typedef bWTF__StringView WTF__StringView; // WTF::StringView
typedef bJSC__ThrowScope JSC__ThrowScope; // JSC::ThrowScope
typedef bWTF__StringImpl WTF__StringImpl; // WTF::StringImpl
typedef WebSocketHTTPSClient WebSocketHTTPSClient;
typedef bJSC__VM JSC__VM; // JSC::VM
typedef JSClassRef JSClassRef;
typedef Bun__ArrayBuffer Bun__ArrayBuffer;
@@ -235,9 +237,11 @@ class ScriptArguments;
typedef ErrorableResolvedSource ErrorableResolvedSource;
typedef ErrorableZigString ErrorableZigString;
typedef WebSocketHTTPClient WebSocketHTTPClient;
typedef SystemError SystemError;
typedef Bun__Writable Bun__Writable;
typedef Bun__Readable Bun__Readable;
typedef WebSocketHTTPSClient WebSocketHTTPSClient;
typedef JSClassRef JSClassRef;
typedef Bun__ArrayBuffer Bun__ArrayBuffer;
typedef ZigException ZigException;
@@ -792,6 +796,22 @@ ZIG_DECL JSC__JSValue ArrayBufferSink__write(JSC__JSGlobalObject* arg0, JSC__Cal
#ifdef __cplusplus
ZIG_DECL void Bun__WebSocketHTTPClient__cancel(WebSocketHTTPClient* arg0);
ZIG_DECL WebSocketHTTPClient* Bun__WebSocketHTTPClient__connect(JSC__JSGlobalObject* arg0, void* arg1, void* arg2, const ZigString* arg3, uint16_t arg4, const ZigString* arg5, const ZigString* arg6);
ZIG_DECL void Bun__WebSocketHTTPClient__register(JSC__JSGlobalObject* arg0, void* arg1, void* arg2);
#endif
#ifdef __cplusplus
ZIG_DECL void Bun__WebSocketHTTPSClient__cancel(WebSocketHTTPSClient* arg0);
ZIG_DECL WebSocketHTTPSClient* Bun__WebSocketHTTPSClient__connect(JSC__JSGlobalObject* arg0, void* arg1, void* arg2, const ZigString* arg3, uint16_t arg4, const ZigString* arg5, const ZigString* arg6);
ZIG_DECL void Bun__WebSocketHTTPSClient__register(JSC__JSGlobalObject* arg0, void* arg1, void* arg2);
#endif
#ifdef __cplusplus
ZIG_DECL void Bun__Process__exit(JSC__JSGlobalObject* arg0, int32_t arg1);
ZIG_DECL JSC__JSValue Bun__Process__getArgv(JSC__JSGlobalObject* arg0);
ZIG_DECL JSC__JSValue Bun__Process__getCwd(JSC__JSGlobalObject* arg0);

View File

@@ -65,6 +65,9 @@ pub const struct_WebCore__FetchHeaders = bindings.FetchHeaders;
pub const StringPointer = @import("../../../api/schema.zig").Api.StringPointer;
pub const struct_VirtualMachine = bindings.VirtualMachine;
pub const ArrayBufferSink = @import("../webcore/streams.zig").ArrayBufferSink;
pub const WebSocketHTTPClient = bindings.WebSocketHTTPClient;
pub const WebSocketHTTPSClient = bindings.WebSocketHTTPSClient;
// GENERATED CODE - DO NOT MODIFY BY HAND
pub const ptrdiff_t = c_long;
@@ -261,7 +264,6 @@ pub extern fn JSC__JSGlobalObject__putCachedObject(arg0: [*c]JSC__JSGlobalObject
pub extern fn JSC__JSGlobalObject__regExpPrototype(arg0: [*c]JSC__JSGlobalObject) ?*JSC__RegExpPrototype;
pub extern fn JSC__JSGlobalObject__setIteratorPrototype(arg0: [*c]JSC__JSGlobalObject) ?*JSC__SetIteratorPrototype;
pub extern fn JSC__JSGlobalObject__startRemoteInspector(arg0: [*c]JSC__JSGlobalObject, arg1: [*c]u8, arg2: u16) bool;
pub extern fn JSC__JSGlobalObject__stopRemoteInspector(arg0: [*c]JSC__JSGlobalObject) void;
pub extern fn JSC__JSGlobalObject__stringPrototype(arg0: [*c]JSC__JSGlobalObject) ?*JSC__StringPrototype;
pub extern fn JSC__JSGlobalObject__symbolPrototype(arg0: [*c]JSC__JSGlobalObject) [*c]JSC__JSObject;
pub extern fn JSC__JSGlobalObject__vm(arg0: [*c]JSC__JSGlobalObject) [*c]JSC__VM;

View File

@@ -10,7 +10,6 @@ class GlobalObject;
#include "headers-handwritten.h"
#include "BunClientData.h"
#include "WebCoreJSBuiltinInternals.h"
#include "JavaScriptCore/CallFrame.h"
#include "js_native_api_types.h"
#include "JavaScriptCore/JSWeakValue.h"

View File

@@ -33,7 +33,6 @@
#include "headers-handwritten.h"
#include "BunClientData.h"
#include "WebCoreJSBuiltinInternals.h"
#include "JavaScriptCore/CallFrame.h"
#if defined(__APPLE__)

View File

@@ -156,8 +156,8 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj
// case MerchantValidationEventInterfaceType:
// return createWrapper<MerchantValidationEvent>(globalObject, WTFMove(impl));
// #endif
// case MessageEventInterfaceType:
// return createWrapper<MessageEvent>(globalObject, WTFMove(impl));
case MessageEventInterfaceType:
return createWrapper<MessageEvent>(globalObject, WTFMove(impl));
// case MouseEventInterfaceType:
// return createWrapper<MouseEvent>(globalObject, WTFMove(impl));
// case MutationEventInterfaceType:

View File

@@ -146,8 +146,8 @@
// #include "MerchantValidationEvent.h"
// #include "JSMerchantValidationEvent.h"
// #endif
// #include "MessageEvent.h"
// #include "JSMessageEvent.h"
#include "MessageEvent.h"
#include "JSMessageEvent.h"
// #include "MouseEvent.h"
// #include "JSMouseEvent.h"
// #include "MutationEvent.h"

View File

@@ -419,9 +419,10 @@ static inline JSC::EncodedJSValue jsMessageEventPrototypeFunction_initMessageEve
// RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
// EnsureStillAliveScope argument7 = callFrame->argument(7);
// auto messagePorts = JSArray::create(lexicalGlobalObject.vm(), lexicalGlobalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0);
auto messagePorts = Converter<IDLSequence<IDLInterface<MessagePort>>>::ReturnType {};
// auto messagePorts = Converter<IDLSequence<IDLInterface<MessagePort>>>::ReturnType {};
RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.initMessageEvent(WTFMove(type), WTFMove(bubbles), WTFMove(cancelable), WTFMove(data), WTFMove(originArg), WTFMove(lastEventId), WTFMove(source), WTFMove(messagePorts)); })));
// RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.initMessageEvent(WTFMove(type), WTFMove(bubbles), WTFMove(cancelable), WTFMove(data), WTFMove(originArg), WTFMove(lastEventId), WTFMove(source), WTFMove(messagePorts)); })));
RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.initMessageEvent(WTFMove(type), WTFMove(bubbles), WTFMove(cancelable), WTFMove(data), WTFMove(originArg), WTFMove(lastEventId), WTFMove(source)); })));
}
JSC_DEFINE_HOST_FUNCTION(jsMessageEventPrototypeFunction_initMessageEvent, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))

View File

@@ -31,7 +31,8 @@
#include "config.h"
#include "WebSocket.h"
#include "WebSocketStream.h"
#include "headers.h"
// #include "Blob.h"
#include "CloseEvent.h"
// #include "ContentSecurityPolicy.h"
@@ -75,9 +76,6 @@
// #include "WebCoreThreadRun.h"
// #endif
namespace WebCore {
using WebSocketChannel = WebSocketStream;
using ThreadableWebSocketChannel = WebSocketStream;
using WebSocketChannelClient = WebSocketStream;
WTF_MAKE_ISO_ALLOCATED_IMPL(WebSocket);
static size_t getFramingOverhead(size_t payloadSize)
@@ -170,9 +168,9 @@ WebSocket::~WebSocket()
if (m_upgradeClient != nullptr) {
void* upgradeClient = m_upgradeClient;
if (m_isSecure) {
Bun_SecureWebSocketUpgradeClient__cancel(upgradeClient);
Bun__WebSocketHTTPSClient__cancel(upgradeClient);
} else {
Bun_WebSocketUpgradeClient__cancel(upgradeClient);
Bun__WebSocketHTTPClient__cancel(upgradeClient);
}
}
@@ -374,11 +372,11 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr
if (is_secure) {
us_socket_context_t* ctx = scriptExecutionContext()->webSocketContext<true>();
RELEASE_ASSERT(ctx);
this->m_upgradeClient = Bun_SecureWebSocketUpgradeClient__connect(scriptExecutionContext()->jsGlobalObject(), ctx, this, &host, port, &path, &clientProtocolString);
this->m_upgradeClient = Bun__WebSocketHTTPSClient__connect(scriptExecutionContext()->jsGlobalObject(), ctx, this, &host, port, &path, &clientProtocolString);
} else {
us_socket_context_t* ctx = scriptExecutionContext()->webSocketContext<false>();
RELEASE_ASSERT(ctx);
this->m_upgradeClient = Bun_WebSocketUpgradeClient__connect(scriptExecutionContext()->jsGlobalObject(), ctx, this, &host, port, &path, &clientProtocolString);
this->m_upgradeClient = Bun__WebSocketHTTPClient__connect(scriptExecutionContext()->jsGlobalObject(), ctx, this, &host, port, &path, &clientProtocolString);
}
if (this->m_upgradeClient == nullptr) {
@@ -455,7 +453,6 @@ ExceptionOr<void> WebSocket::send(ArrayBufferView& arrayBufferView)
m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, getFramingOverhead(payloadSize));
return {};
}
ASSERT(m_channel);
auto buffer = arrayBufferView.unsharedBuffer().get();
char* baseAddress = reinterpret_cast<char*>(buffer->data()) + arrayBufferView.byteOffset();
@@ -522,8 +519,8 @@ ExceptionOr<void> WebSocket::close(std::optional<unsigned short> optionalCode, c
{
CString utf8 = reason.utf8(StrictConversionReplacingUnpairedSurrogatesWithFFFD);
int code = optionalCode ? optionalCode.value() : static_cast<int>(WebSocketChannel::CloseEventCodeNotSpecified);
if (code == WebSocketChannel::CloseEventCodeNotSpecified)
int code = optionalCode ? optionalCode.value() : static_cast<int>(0);
if (code == 0)
LOG(Network, "WebSocket %p close() without code and reason", this);
else {
LOG(Network, "WebSocket %p close() code=%d reason='%s'", this, code, reason.utf8().data());
@@ -543,9 +540,9 @@ ExceptionOr<void> WebSocket::close(std::optional<unsigned short> optionalCode, c
void* upgradeClient = m_upgradeClient;
m_upgradeClient = nullptr;
if (m_isSecure) {
Bun_SecureWebSocketUpgradeClient__cancel(upgradeClient);
Bun__WebSocketHTTPSClient__cancel(upgradeClient);
} else {
Bun_WebSocketUpgradeClient__cancel(upgradeClient);
Bun__WebSocketHTTPClient__cancel(upgradeClient);
}
}
return {};
@@ -581,11 +578,6 @@ ExceptionOr<void> WebSocket::close(std::optional<unsigned short> optionalCode, c
return {};
}
WebSocketChannelClient* WebSocket::channel() const
{
return m_channel;
}
const URL& WebSocket::url() const
{
return m_url;
@@ -697,7 +689,7 @@ void WebSocket::didConnect()
if (m_state == CLOSED)
return;
if (m_state != CONNECTING) {
didClose(0, ClosingHandshakeIncomplete, WebSocketChannel::CloseEventCodeAbnormalClosure, emptyString());
didClose(0, 0, emptyString());
return;
}
ASSERT(scriptExecutionContext());
@@ -787,7 +779,7 @@ void WebSocket::didStartClosingHandshake()
// });
}
void WebSocket::didClose(unsigned unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
void WebSocket::didClose(unsigned unhandledBufferedAmount, unsigned short code, const String& reason)
{
LOG(Network, "WebSocket %p didClose()", this);
if (this->m_connectedWebSocketKind == ConnectedWebSocketKind::None)
@@ -805,7 +797,7 @@ void WebSocket::didClose(unsigned unhandledBufferedAmount, ClosingHandshakeCompl
// }
// }
bool wasClean = m_state == CLOSING && !unhandledBufferedAmount && closingHandshakeCompletion == ClosingHandshakeComplete && code != WebSocketChannel::CloseEventCodeAbnormalClosure;
bool wasClean = m_state == CLOSING && !unhandledBufferedAmount && code != 0; // WebSocketChannel::CloseEventCodeAbnormalClosure;
m_state = CLOSED;
m_bufferedAmount = unhandledBufferedAmount;
ASSERT(scriptExecutionContext());

View File

@@ -37,7 +37,10 @@
#include <wtf/HashSet.h>
#include <wtf/Lock.h>
#include "WebSocketStream.h"
namespace uWS {
template<bool, bool, typename>
struct WebSocket;
}
namespace JSC {
class ArrayBuffer;
@@ -49,14 +52,6 @@ namespace WebCore {
// class Blob;
class WebSocket final : public RefCounted<WebSocket>, public EventTargetWithInlineData, public ContextDestructionObserver {
WTF_MAKE_ISO_ALLOCATED(WebSocket);
friend struct uWS::WebSocket<false, false, WebSocket*>;
friend struct uWS::WebSocket<false, true, WebSocket*>;
friend struct uWS::WebSocket<true, false, WebSocket*>;
friend struct uWS::WebSocket<true, true, WebSocket*>;
friend WebCore::WebSocketStream;
friend WebCore::SecureWebSocketStream;
friend WebCore::ServerWebSocketStream;
friend WebCore::ServerSecureWebSocketStream;
public:
static ASCIILiteral subprotocolSeparator();
@@ -85,8 +80,6 @@ public:
ExceptionOr<void> close(std::optional<unsigned short> code, const String& reason);
WebSocketStream* channel() const;
const URL& url() const;
State readyState() const;
unsigned bufferedAmount() const;
@@ -102,16 +95,20 @@ public:
using RefCounted::deref;
using RefCounted::ref;
void didConnect();
void didClose(unsigned unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason);
void didClose(unsigned unhandledBufferedAmount, unsigned short code, const String& reason);
void didConnect(us_socket_t* socket, char* bufferedData, size_t bufferedDataSize);
void didFailToConnect(int32_t code);
void didReceiveMessage(String&& message);
void didReceiveData(const char* data, size_t length);
void didReceiveBinaryData(Vector<uint8_t>&&);
private:
typedef union AnyWebSocket {
uWS::WebSocket<false, false, WebSocket*>* client;
uWS::WebSocket<true, false, WebSocket*>* clientSSL;
uWS::WebSocket<false, true, WebSocket*>* server;
uWS::WebSocket<true, true, WebSocket*>* serverSSL;
uWS::WebSocket<false, false, WebCore::WebSocket*>* client;
uWS::WebSocket<true, false, WebCore::WebSocket*>* clientSSL;
uWS::WebSocket<false, true, WebCore::WebSocket*>* server;
uWS::WebSocket<true, true, WebCore::WebSocket*>* serverSSL;
} AnyWebSocket;
enum ConnectedWebSocketKind {
None,
@@ -137,9 +134,6 @@ private:
void refEventTarget() final { ref(); }
void derefEventTarget() final { deref(); }
void didReceiveMessage(String&& message);
void didReceiveData(const char* data, size_t length);
void didReceiveBinaryData(Vector<uint8_t>&&);
void didReceiveMessageError(WTF::StringImpl::StaticStringImpl* reason);
void didUpdateBufferedAmount(unsigned bufferedAmount);
void didStartClosingHandshake();
@@ -152,8 +146,6 @@ private:
enum class BinaryType { Blob,
ArrayBuffer };
WebSocketStream* m_channel { nullptr };
State m_state { CONNECTING };
URL m_url;
unsigned m_bufferedAmount { 0 };

View File

@@ -1,88 +1,10 @@
#include "root.h"
#include "headers.h"
#include "WebSocketStream.h"
#include "ScriptExecutionContext.h"
#include <uws/src/App.h>
#include <uws/uSockets/src/libusockets.h>
namespace WebCore {
template<bool SSL, bool isServer>
void registerHTTPContextForWebSocket(ScriptExecutionContext* script, us_socket_context_t* ctx, us_loop_t* loop)
{
if constexpr (!isServer) {
if constexpr (SSL) {
Bun__SecureWebSocketUpgradeClient__register(script->jsGlobalObject(), loop, ctx);
} else {
Bun__WebSocketUpgradeClient__register(script->jsGlobalObject(), loop, ctx);
}
} else {
RELEASE_ASSERT_NOT_REACHED();
}
}
template<bool SSL, bool isServer>
uWS::WebSocketContext<SSL, isServer, ScriptExecutionContext*>* registerWebSocketClientContext(ScriptExecutionContext* script, us_socket_context_t* parent)
{
uWS::Loop* loop = uWS::Loop::get();
uWS::WebSocketContext<SSL, isServer, ScriptExecutionContext*>* ctx = uWS::WebSocketContext<SSL, isServer>::create(loop, parent, nullptr);
auto* opts = ctx->getExt();
ScriptExecutionContext** scriptCtx = ctx->getUserData();
*scriptCtx = script;
/* Maximum message size we can receive */
static unsigned int maxPayloadLength = 128 * 1024 * 1024;
/* 2 minutes timeout is good */
static unsigned short idleTimeout = 120;
/* 64kb backpressure is probably good */
static unsigned int maxBackpressure = 128 * 1024 * 1024;
static bool closeOnBackpressureLimit = false;
/* This one depends on kernel timeouts and is a bad default */
static bool resetIdleTimeoutOnSend = false;
/* A good default, esp. for newcomers */
static bool sendPingsAutomatically = true;
/* Maximum socket lifetime in seconds before forced closure (defaults to disabled) */
static unsigned short maxLifetime = 0;
opts->maxPayloadLength = maxPayloadLength;
opts->maxBackpressure = maxBackpressure;
opts->closeOnBackpressureLimit = closeOnBackpressureLimit;
opts->resetIdleTimeoutOnSend = resetIdleTimeoutOnSend;
opts->sendPingsAutomatically = sendPingsAutomatically;
// opts->compression = compression;
// TODO:
opts->compression = false;
opts->openHandler = [](uWS::WebSocket<SSL, isServer, WebCore::WebSocket>* ws) {
auto* webSocket = ws->getUserData();
webSocket->didOpen();
};
opts->messageHandler = [](uWS::WebSocket<SSL, isServer, WebCore::WebSocket>* ws, std::string_view input, uWS::OpCode opCode) {
auto* webSocket = ws->getUserData();
if (opCode == uWS::OpCode::BINARY) {
webSocket->didReceiveBinaryData({ input.data(), input.length() });
} else {
webSocket->didReceiveMessage(WTF::String::fromUTF8(input.data(), input.length()));
}
};
// pts->drainHandler = [](uWS::WebSocket<SSL, isServer, WebCore::WebSocket>* ws, std::string_view input, uWS::OpCode opCode) {
// auto* webSocket = ws->getUserData();
// webSocket->didReceiveData(input.data(), input.length());
// };
opts->closeHandler = [](uWS::WebSocket<SSL, isServer, WebCore::WebSocket>* ws, int code, std::string_view message) {
auto* webSocket = ws->getUserData();
webSocket->didClose(
ws->getBufferedAmount(),
code,
WTF::String::fromUTF8(
message.data(),
message.length()));
};
return ctx;
}
}

View File

@@ -29,6 +29,7 @@
*/
#pragma once
#include "root.h"
#include "wtf/text/StringImpl.h"
#include "wtf/text/StringView.h"
@@ -36,6 +37,8 @@
#include "wtf/URL.h"
#include "wtf/Vector.h"
#include "wtf/Function.h"
#include "ScriptExecutionContext.h"
#include "headers.h"
namespace uWS {
template<bool, bool, typename>
@@ -111,15 +114,4 @@ public:
}
};
template<bool isSSL, bool isServer>
void registerHTTPContextForWebSocket(ScriptExecutionContext*, us_socket_context_t*);
template<bool SSL, bool isServer>
uWS::WebSocketContext<SSL, isServer, ScriptExecutionContext*>* registerWebSocketClientContext(ScriptExecutionContext*, us_socket_context_t* parent);
using WebSocketStream = WebSocketStreamBase<false, false>;
using SecureWebSocketStream = WebSocketStreamBase<true, false>;
using ServerWebSocketStream = WebSocketStreamBase<false, true>;
using ServerSecureWebSocketStream = WebSocketStreamBase<true, true>;
} // namespace WebCore