diff options
Diffstat (limited to 'src/bun.js')
-rw-r--r-- | src/bun.js/api/server.zig | 53 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 26 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.h | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.zig | 17 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/WebSocket.cpp | 27 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/WebSocket.h | 28 |
6 files changed, 75 insertions, 78 deletions
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index f52c08301..9625ff693 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -3560,11 +3560,6 @@ pub const ServerWebSocket = struct { if (message_value.asArrayBuffer(globalThis)) |array_buffer| { const buffer = array_buffer.slice(); - if (buffer.len == 0) { - globalThis.throw("publish requires a non-empty message", .{}); - return .zero; - } - const result = if (!publish_to_self) this.websocket.publish(topic_slice.slice(), buffer, .binary, compress) else @@ -3580,9 +3575,6 @@ pub const ServerWebSocket = struct { { var string_slice = message_value.toSlice(globalThis, bun.default_allocator); defer string_slice.deinit(); - if (string_slice.len == 0) { - return JSValue.jsNumber(0); - } const buffer = string_slice.slice(); @@ -3634,10 +3626,6 @@ pub const ServerWebSocket = struct { var topic_slice = topic_value.toSlice(globalThis, bun.default_allocator); defer topic_slice.deinit(); - if (topic_slice.len == 0) { - globalThis.throw("publishText requires a non-empty topic", .{}); - return .zero; - } const compress = args.len > 1 and compress_value.toBoolean(); @@ -3648,9 +3636,6 @@ pub const ServerWebSocket = struct { var string_slice = message_value.toSlice(globalThis, bun.default_allocator); defer string_slice.deinit(); - if (string_slice.len == 0) { - return JSValue.jsNumber(0); - } const buffer = string_slice.slice(); @@ -3715,10 +3700,6 @@ pub const ServerWebSocket = struct { }; const buffer = array_buffer.slice(); - if (buffer.len == 0) { - return JSC.JSValue.jsNumber(0); - } - const result = if (!publish_to_self) this.websocket.publish(topic_slice.slice(), buffer, .binary, compress) else @@ -3883,10 +3864,6 @@ pub const ServerWebSocket = struct { } if (message_value.asArrayBuffer(globalThis)) |buffer| { - if (buffer.len == 0) { - return JSValue.jsNumber(0); - } - switch (this.websocket.send(buffer.slice(), .binary, compress, true)) { .backpressure => { log("send() backpressure ({d} bytes)", .{buffer.len}); @@ -3906,9 +3883,6 @@ pub const ServerWebSocket = struct { { var string_slice = message_value.toSlice(globalThis, bun.default_allocator); defer string_slice.deinit(); - if (string_slice.len == 0) { - return JSValue.jsNumber(0); - } const buffer = string_slice.slice(); switch (this.websocket.send(buffer, .text, compress, true)) { @@ -3960,9 +3934,6 @@ pub const ServerWebSocket = struct { var string_slice = message_value.toSlice(globalThis, bun.default_allocator); defer string_slice.deinit(); - if (string_slice.len == 0) { - return JSValue.jsNumber(0); - } const buffer = string_slice.slice(); switch (this.websocket.send(buffer, .text, compress, true)) { @@ -3994,9 +3965,6 @@ pub const ServerWebSocket = struct { var string_slice = message_str.toSlice(globalThis, bun.default_allocator); defer string_slice.deinit(); - if (string_slice.len == 0) { - return JSValue.jsNumber(0); - } const buffer = string_slice.slice(); switch (this.websocket.send(buffer, .text, compress, true)) { @@ -4043,10 +4011,6 @@ pub const ServerWebSocket = struct { return .zero; }; - if (buffer.len == 0) { - return JSValue.jsNumber(0); - } - switch (this.websocket.send(buffer.slice(), .binary, compress, true)) { .backpressure => { log("sendBinary() backpressure ({d} bytes)", .{buffer.len}); @@ -4076,10 +4040,6 @@ pub const ServerWebSocket = struct { const buffer = array_buffer.slice(); - if (buffer.len == 0) { - return JSValue.jsNumber(0); - } - switch (this.websocket.send(buffer, .binary, compress, true)) { .backpressure => { log("sendBinary() backpressure ({d} bytes)", .{buffer.len}); @@ -4416,17 +4376,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { const compress = (compress_value orelse JSValue.jsBoolean(true)).toBoolean(); - if (message_value.isEmptyOrUndefinedOrNull()) { - JSC.JSError(this.vm.allocator, "publish requires a non-empty message", .{}, globalThis, exception); - return .zero; - } - if (message_value.asArrayBuffer(globalThis)) |buffer| { - if (buffer.len == 0) { - JSC.JSError(this.vm.allocator, "publish requires a non-empty message", .{}, globalThis, exception); - return .zero; - } - return JSValue.jsNumber( // if 0, return 0 // else return number of bytes sent @@ -4437,9 +4387,6 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { { var string_slice = message_value.toSlice(globalThis, bun.default_allocator); defer string_slice.deinit(); - if (string_slice.len == 0) { - return JSValue.jsNumber(0); - } const buffer = string_slice.slice(); return JSValue.jsNumber( diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index c00670289..b3236a4a2 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -1021,6 +1021,20 @@ JSC_DEFINE_HOST_FUNCTION(functionBunSleepThenCallback, return JSC::JSValue::encode(promise); } +using MicrotaskCallback = void (*)(void*); + +JSC_DEFINE_HOST_FUNCTION(functionNativeMicrotaskTrampoline, + (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + JSCell* cellPtr = callFrame->uncheckedArgument(0).asCell(); + JSCell* callbackPtr = callFrame->uncheckedArgument(1).asCell(); + + void* cell = reinterpret_cast<void*>(cellPtr); + auto* callback = reinterpret_cast<MicrotaskCallback>(callbackPtr); + callback(cell); + return JSValue::encode(jsUndefined()); +} + JSC_DEFINE_HOST_FUNCTION(functionBunSleep, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { @@ -3027,6 +3041,11 @@ void GlobalObject::finishCreation(VM& vm) init.set(JSFunction::create(init.vm, init.owner, 4, "performMicrotaskVariadic"_s, jsFunctionPerformMicrotaskVariadic, ImplementationVisibility::Public)); }); + m_nativeMicrotaskTrampoline.initLater( + [](const Initializer<JSFunction>& init) { + init.set(JSFunction::create(init.vm, init.owner, 2, ""_s, functionNativeMicrotaskTrampoline, ImplementationVisibility::Public)); + }); + m_navigatorObject.initLater( [](const Initializer<JSObject>& init) { int cpuCount = 0; @@ -4225,6 +4244,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_JSFileSinkControllerPrototype.visit(visitor); thisObject->m_JSHTTPSResponseControllerPrototype.visit(visitor); thisObject->m_navigatorObject.visit(visitor); + thisObject->m_nativeMicrotaskTrampoline.visit(visitor); thisObject->m_performanceObject.visit(visitor); thisObject->m_primordialsObject.visit(visitor); thisObject->m_processEnvObject.visit(visitor); @@ -4387,6 +4407,12 @@ extern "C" void JSC__JSGlobalObject__reload(JSC__JSGlobalObject* arg0) globalObject->reload(); } +extern "C" void JSC__JSGlobalObject__queueMicrotaskCallback(Zig::GlobalObject* globalObject, void* ptr, MicrotaskCallback callback) +{ + JSFunction* function = globalObject->nativeMicrotaskTrampoline(); + globalObject->queueMicrotask(function, JSValue(reinterpret_cast<JSC::JSCell*>(ptr)), JSValue(reinterpret_cast<JSC::JSCell*>(callback)), jsUndefined(), jsUndefined()); +} + JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, JSModuleLoader* loader, JSValue key, JSValue referrer, JSValue origin) diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index a5b802ced..da6ba92a0 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -369,6 +369,7 @@ public: mutable WriteBarrier<JSFunction> m_thenables[promiseFunctionsSize + 1]; JSObject* navigatorObject(); + JSFunction* nativeMicrotaskTrampoline() { return m_nativeMicrotaskTrampoline.getInitializedOnMainThread(this); } void trackFFIFunction(JSC::JSFunction* function) { @@ -466,6 +467,7 @@ private: */ LazyProperty<JSGlobalObject, JSC::Structure> m_pendingVirtualModuleResultStructure; LazyProperty<JSGlobalObject, JSFunction> m_performMicrotaskFunction; + LazyProperty<JSGlobalObject, JSFunction> m_nativeMicrotaskTrampoline; LazyProperty<JSGlobalObject, JSFunction> m_performMicrotaskVariadicFunction; LazyProperty<JSGlobalObject, JSFunction> m_emitReadableNextTickFunction; LazyProperty<JSGlobalObject, JSMap> m_lazyReadableStreamPrototypeMap; diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 277172b81..07882d857 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -2732,6 +2732,23 @@ pub const JSGlobalObject = extern struct { this.vm().throwError(this, this.createErrorInstance(Output.prettyFmt(fmt, false), args)); } } + extern fn JSC__JSGlobalObject__queueMicrotaskCallback(*JSGlobalObject, *anyopaque, Function: *const (fn (*anyopaque) callconv(.C) void)) void; + pub fn queueMicrotaskCallback( + this: *JSGlobalObject, + ctx_val: anytype, + comptime Function: fn (ctx: @TypeOf(ctx_val)) void, + ) void { + JSC.markBinding(@src()); + const Fn = Function; + const ContextType = @TypeOf(ctx_val); + const Wrapper = struct { + pub fn call(p: *anyopaque) callconv(.C) void { + Fn(bun.cast(ContextType, p)); + } + }; + + JSC__JSGlobalObject__queueMicrotaskCallback(this, ctx_val, &Wrapper.call); + } pub fn queueMicrotask( this: *JSGlobalObject, diff --git a/src/bun.js/bindings/webcore/WebSocket.cpp b/src/bun.js/bindings/webcore/WebSocket.cpp index a346175df..1d6392f44 100644 --- a/src/bun.js/bindings/webcore/WebSocket.cpp +++ b/src/bun.js/bindings/webcore/WebSocket.cpp @@ -458,8 +458,8 @@ ExceptionOr<void> WebSocket::send(const String& message) return {}; } - if (message.length() > 0) - this->sendWebSocketString(message); + // 0-length is allowed + this->sendWebSocketString(message); return {}; } @@ -477,8 +477,8 @@ ExceptionOr<void> WebSocket::send(ArrayBuffer& binaryData) } char* data = static_cast<char*>(binaryData.data()); size_t length = binaryData.byteLength(); - if (length > 0) - this->sendWebSocketData(data, length); + // 0-length is allowed + this->sendWebSocketData(data, length); return {}; } @@ -498,8 +498,8 @@ ExceptionOr<void> WebSocket::send(ArrayBufferView& arrayBufferView) auto buffer = arrayBufferView.unsharedBuffer().get(); char* baseAddress = reinterpret_cast<char*>(buffer->data()) + arrayBufferView.byteOffset(); size_t length = arrayBufferView.byteLength(); - if (length > 0) - this->sendWebSocketData(baseAddress, length); + // 0-length is allowed + this->sendWebSocketData(baseAddress, length); return {}; } @@ -1232,14 +1232,19 @@ extern "C" void WebSocket__didCloseWithErrorCode(WebCore::WebSocket* webSocket, extern "C" void WebSocket__didReceiveText(WebCore::WebSocket* webSocket, bool clone, const ZigString* str) { - WTF::String wtf_str = Zig::toString(*str); - if (clone) { - wtf_str = wtf_str.isolatedCopy(); - } - + WTF::String wtf_str = clone ? Zig::toStringCopy(*str) : Zig::toString(*str); webSocket->didReceiveMessage(WTFMove(wtf_str)); } extern "C" void WebSocket__didReceiveBytes(WebCore::WebSocket* webSocket, uint8_t* bytes, size_t len) { webSocket->didReceiveBinaryData({ bytes, len }); } + +extern "C" void WebSocket__incrementPendingActivity(WebCore::WebSocket* webSocket) +{ + webSocket->incPendingActivityCount(); +} +extern "C" void WebSocket__decrementPendingActivity(WebCore::WebSocket* webSocket) +{ + webSocket->decPendingActivityCount(); +}
\ No newline at end of file diff --git a/src/bun.js/bindings/webcore/WebSocket.h b/src/bun.js/bindings/webcore/WebSocket.h index 42261cfc4..846bd186b 100644 --- a/src/bun.js/bindings/webcore/WebSocket.h +++ b/src/bun.js/bindings/webcore/WebSocket.h @@ -111,6 +111,20 @@ public: return m_hasPendingActivity.load(); } + void incPendingActivityCount() + { + m_pendingActivityCount++; + ref(); + updateHasPendingActivity(); + } + + void decPendingActivityCount() + { + m_pendingActivityCount--; + deref(); + updateHasPendingActivity(); + } + private: typedef union AnyWebSocket { WebSocketClient* client; @@ -147,20 +161,6 @@ private: void sendWebSocketString(const String& message); void sendWebSocketData(const char* data, size_t length); - void incPendingActivityCount() - { - m_pendingActivityCount++; - ref(); - updateHasPendingActivity(); - } - - void decPendingActivityCount() - { - m_pendingActivityCount--; - deref(); - updateHasPendingActivity(); - } - void failAsynchronously(); enum class BinaryType { Blob, |