diff options
Diffstat (limited to 'src/bun.js')
-rw-r--r-- | src/bun.js/api/bun/socket.zig | 22 | ||||
-rw-r--r-- | src/bun.js/base.zig | 99 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 7 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.zig | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes.zig | 4 | ||||
-rw-r--r-- | src/bun.js/net.exports.js | 11 |
6 files changed, 129 insertions, 15 deletions
diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 925db901d..cf482e242 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -65,6 +65,9 @@ fn normalizeHost(input: anytype) @TypeOf(input) { return input; } + +const BinaryType = JSC.BinaryType; + const Handlers = struct { onOpen: JSC.JSValue = .zero, onClose: JSC.JSValue = .zero, @@ -75,7 +78,7 @@ const Handlers = struct { onEnd: JSC.JSValue = .zero, onError: JSC.JSValue = .zero, - encoding: JSC.Node.Encoding = .utf8, + binary_type: BinaryType = .Buffer, vm: *JSC.VirtualMachine, globalObject: *JSC.JSGlobalObject, @@ -150,7 +153,6 @@ const Handlers = struct { .{ "onWritable", "drain" }, .{ "onOpen", "open" }, .{ "onClose", "close" }, - .{ "onData", "data" }, .{ "onTimeout", "timeout" }, .{ "onConnectError", "connectError" }, .{ "onEnd", "end" }, @@ -172,6 +174,18 @@ const Handlers = struct { return null; } + if (opts.getTruthy(globalObject, "binaryType")) |binary_type_value| { + if (!binary_type_value.isString()) { + exception.* = JSC.toInvalidArguments("Expected \"binaryType\" to be a string", .{}, globalObject).asObjectRef(); + return null; + } + + handlers.binary_type = BinaryType.fromJSValue(globalObject, binary_type_value) orelse { + exception.* = JSC.toInvalidArguments("Expected 'binaryType' to be 'arraybuffer', 'uint8array', 'buffer'", .{}, globalObject).asObjectRef(); + return null; + }; + } + return handlers; } @@ -1144,7 +1158,7 @@ fn NewSocket(comptime ssl: bool) type { const globalObject = handlers.globalObject; const this_value = this.getThisValue(globalObject); - const output_value = JSC.ArrayBuffer.create(globalObject, data, .Uint8Array); + const output_value = handlers.binary_type.toJS(data, globalObject); // const encoding = handlers.encoding; const result = callback.callWithThis(globalObject, this_value, &[_]JSValue{ this_value, @@ -1288,7 +1302,7 @@ fn NewSocket(comptime ssl: bool) type { } // we don't cork yet but we might later const res = this.socket.write(buffer, is_end); - log("write({d}, {any})", .{ buffer.len, is_end }); + log("write({d}, {any}) = {d}", .{ buffer.len, is_end, res }); return res; } diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig index f2a305564..10a182c60 100644 --- a/src/bun.js/base.zig +++ b/src/bun.js/base.zig @@ -1715,13 +1715,18 @@ pub const ArrayBuffer = extern struct { pub fn create(globalThis: *JSC.JSGlobalObject, bytes: []const u8, comptime kind: JSC.JSValue.JSType) JSValue { JSC.markBinding(@src()); return switch (comptime kind) { - .Uint8Array => Bun__createUint8ArrayForCopy(globalThis, bytes.ptr, bytes.len), + .Uint8Array => Bun__createUint8ArrayForCopy(globalThis, bytes.ptr, bytes.len, false), .ArrayBuffer => Bun__createArrayBufferForCopy(globalThis, bytes.ptr, bytes.len), else => @compileError("Not implemented yet"), }; } - extern "C" fn Bun__createUint8ArrayForCopy(*JSC.JSGlobalObject, ptr: ?*const anyopaque, len: usize) JSValue; + pub fn createBuffer(globalThis: *JSC.JSGlobalObject, bytes: []const u8) JSValue { + JSC.markBinding(@src()); + return Bun__createUint8ArrayForCopy(globalThis, bytes.ptr, bytes.len, true); + } + + extern "C" fn Bun__createUint8ArrayForCopy(*JSC.JSGlobalObject, ptr: ?*const anyopaque, len: usize, buffer: bool) JSValue; extern "C" fn Bun__createArrayBufferForCopy(*JSC.JSGlobalObject, ptr: ?*const anyopaque, len: usize) JSValue; pub fn fromTypedArray(ctx: JSC.C.JSContextRef, value: JSC.JSValue, _: JSC.C.ExceptionRef) ArrayBuffer { @@ -3994,3 +3999,93 @@ pub const Strong = extern struct { ref.destroy(); } }; + +pub const BinaryType = enum { + Buffer, + ArrayBuffer, + Uint8Array, + Uint16Array, + Uint32Array, + Int8Array, + Int16Array, + Int32Array, + Float32Array, + Float64Array, + // DataView, + + pub fn toJSType(this: BinaryType) JSC.JSValue.JSType { + return switch (this) { + .ArrayBuffer => .ArrayBuffer, + .Buffer => .Uint8Array, + // .DataView => .DataView, + .Float32Array => .Float32Array, + .Float64Array => .Float64Array, + .Int16Array => .Int16Array, + .Int32Array => .Int32Array, + .Int8Array => .Int8Array, + .Uint16Array => .Uint16Array, + .Uint32Array => .Uint32Array, + .Uint8Array => .Uint8Array, + }; + } + + pub fn toTypedArrayType(this: BinaryType) JSC.C.JSTypedArrayType { + return this.toJSType().toC(); + } + + const Map = bun.ComptimeStringMap( + BinaryType, + .{ + .{ "ArrayBuffer", .ArrayBuffer }, + .{ "Buffer", .Buffer }, + // .{ "DataView", .DataView }, + .{ "Float32Array", .Float32Array }, + .{ "Float64Array", .Float64Array }, + .{ "Int16Array", .Int16Array }, + .{ "Int32Array", .Int32Array }, + .{ "Int8Array", .Int8Array }, + .{ "Uint16Array", .Uint16Array }, + .{ "Uint32Array", .Uint32Array }, + .{ "Uint8Array", .Uint8Array }, + .{ "arraybuffer", .ArrayBuffer }, + .{ "buffer", .Buffer }, + // .{ "dataview", .DataView }, + .{ "float32array", .Float32Array }, + .{ "float64array", .Float64Array }, + .{ "int16array", .Int16Array }, + .{ "int32array", .Int32Array }, + .{ "int8array", .Int8Array }, + .{ "nodebuffer", .Buffer }, + .{ "uint16array", .Uint16Array }, + .{ "uint32array", .Uint32Array }, + .{ "uint8array", .Uint8Array }, + }, + ); + + pub fn fromString(input: []const u8) ?BinaryType { + return Map.get(input); + } + + pub fn fromJSValue(globalThis: *JSC.JSGlobalObject, input: JSValue) ?BinaryType { + if (input.isString()) { + return Map.getWithEql(input.getZigString(globalThis), ZigString.eqlComptime); + } + + return null; + } + + /// This clones bytes + pub fn toJS(this: BinaryType, bytes: []const u8, globalThis: *JSC.JSGlobalObject) JSValue { + switch (this) { + .Buffer => return JSC.ArrayBuffer.createBuffer(globalThis, bytes), + .ArrayBuffer => return JSC.ArrayBuffer.create(globalThis, bytes, .ArrayBuffer), + .Uint8Array => return JSC.ArrayBuffer.create(globalThis, bytes, .Uint8Array), + + // These aren't documented, but they are supported + .Uint16Array, .Uint32Array, .Int8Array, .Int16Array, .Int32Array, .Float32Array, .Float64Array => { + const buffer = JSC.ArrayBuffer.create(globalThis, bytes, .ArrayBuffer); + return JSC.JSValue.c(JSC.C.JSObjectMakeTypedArrayWithArrayBuffer(globalThis, this.toTypedArrayType(), buffer.asObjectRef(), null)); + }, + } + } +}; diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 9f6a13b40..bfd775cde 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -970,10 +970,13 @@ extern "C" JSC__JSValue Bun__createArrayBufferForCopy(JSC::JSGlobalObject* globa RELEASE_AND_RETURN(scope, JSValue::encode(JSC::JSArrayBuffer::create(globalObject->vm(), globalObject->arrayBufferStructure(JSC::ArrayBufferSharingMode::Default), WTFMove(arrayBuffer)))); } -extern "C" JSC__JSValue Bun__createUint8ArrayForCopy(JSC::JSGlobalObject* globalObject, const void* ptr, size_t len) +extern "C" JSC__JSValue Bun__createUint8ArrayForCopy(JSC::JSGlobalObject* globalObject, const void* ptr, size_t len, bool isBuffer) { auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - JSC::JSUint8Array* array = JSC::JSUint8Array::createUninitialized(globalObject, globalObject->m_typedArrayUint8.get(globalObject), len); + JSC::JSUint8Array* array = JSC::JSUint8Array::createUninitialized( + globalObject, + isBuffer ? reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSBufferSubclassStructure() : globalObject->m_typedArrayUint8.get(globalObject), + len); if (UNLIKELY(!array)) { JSC::throwOutOfMemoryError(globalObject, scope); diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 23dd6188f..447c6c043 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -2582,6 +2582,7 @@ pub const JSValue = enum(JSValueReprInt) { .Float32Array => .kJSTypedArrayTypeFloat32Array, .Float64Array => .kJSTypedArrayTypeFloat64Array, .ArrayBuffer => .kJSTypedArrayTypeArrayBuffer, + // .DataView => .kJSTypedArrayTypeDataView, else => .kJSTypedArrayTypeNone, }; } diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index 9962ec7f5..18bf91b99 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -6,8 +6,8 @@ /// 1. `bun src/bun.js/scripts/generate-classes.ts` /// 2. Scan for **/*.classes.ts files in src/bun.js/src /// 3. Generate a JS wrapper for each class in: -/// Zig: generated_classes.zig -/// C++: ZigGeneratedClasses.h, ZigGeneratedClasses.cpp +/// - Zig: generated_classes.zig +/// - C++: ZigGeneratedClasses.h, ZigGeneratedClasses.cpp /// 4. For the Zig code to successfully compile: /// - Add it to generated_classes_list.zig /// - pub usingnamespace JSC.Codegen.JSMyClassName; diff --git a/src/bun.js/net.exports.js b/src/bun.js/net.exports.js index 928189dd3..b4229a271 100644 --- a/src/bun.js/net.exports.js +++ b/src/bun.js/net.exports.js @@ -86,14 +86,14 @@ export const Socket = (function (InternalSocket) { self.emit("error", error); }, - data({ data: self }, { length, buffer }) { - self.bytesRead += length; + data({ data: self }, buffer) { + self.bytesRead += buffer.length; const queue = self.#readQueue; - const ret = new Buffer(buffer); + if (queue.isEmpty()) { - if (self.push(ret)) return; + if (self.push(buffer)) return; } - queue.push(ret); + queue.push(buffer); }, drain: Socket.#Drain, end: Socket.#Close, @@ -120,6 +120,7 @@ export const Socket = (function (InternalSocket) { const self = socket.data; self.emit("timeout"); }, + binaryType: "buffer", }; static #Close(socket) { |