diff options
author | 2022-05-01 07:41:26 -0700 | |
---|---|---|
committer | 2022-05-01 07:41:26 -0700 | |
commit | 3403621fc21fb5827bfdd8405efab410fe45bcf9 (patch) | |
tree | 351c8697f26dfd828512f96288003f2ba2698dfc | |
parent | de23f2f8aa505af99ebf0cdf42d7fa96185b7bdd (diff) | |
download | bun-3403621fc21fb5827bfdd8405efab410fe45bcf9.tar.gz bun-3403621fc21fb5827bfdd8405efab410fe45bcf9.tar.zst bun-3403621fc21fb5827bfdd8405efab410fe45bcf9.zip |
wip Buffer.fill
-rw-r--r-- | src/javascript/jsc/bindings/Buffer.h | 1 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/JSBuffer.cpp | 95 | ||||
-rw-r--r-- | src/javascript/jsc/node/buffer.zig | 166 |
3 files changed, 167 insertions, 95 deletions
diff --git a/src/javascript/jsc/bindings/Buffer.h b/src/javascript/jsc/bindings/Buffer.h index eb7ff26a9..bc3367ad6 100644 --- a/src/javascript/jsc/bindings/Buffer.h +++ b/src/javascript/jsc/bindings/Buffer.h @@ -19,6 +19,7 @@ extern "C" JSC::EncodedJSValue Bun__encoding__toStringLatin1(const uint8_t* inpu extern "C" JSC::EncodedJSValue Bun__encoding__toStringHex(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject); extern "C" JSC::EncodedJSValue Bun__encoding__toStringBase64(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject); extern "C" JSC::EncodedJSValue Bun__encoding__toStringURLSafeBase64(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject); +extern "C" void Bun__Buffer_fill(JSC::JSGlobalObject*, Bun__ArrayBuffer*, ZigString*, uint32_t, uint32_t, WebCore::BufferEncodingType); namespace WebCore { diff --git a/src/javascript/jsc/bindings/JSBuffer.cpp b/src/javascript/jsc/bindings/JSBuffer.cpp index ab5e0341d..8f56703ce 100644 --- a/src/javascript/jsc/bindings/JSBuffer.cpp +++ b/src/javascript/jsc/bindings/JSBuffer.cpp @@ -798,7 +798,100 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob { auto& vm = JSC::getVM(lexicalGlobalObject); - return JSC::JSValue::encode(jsUndefined()); + if (callFrame->argumentCount() < 1) { + return JSValue::encode(castedThis); + } + + auto value = callFrame->uncheckedArgument(0); + + if (!value.isString()) { + auto value_ = value.toInt32() & 0xFF; + + auto value_uint8 = static_cast<uint8_t>(value_); + auto length = castedThis->byteLength(); + auto start = 0; + auto end = length; + if (callFrame->argumentCount() > 1) { + if (auto start_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) { + start = start_.value(); + } else { + return throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s)); + } + if (callFrame->argumentCount() > 2) { + if (auto end_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) { + end = end_.value(); + } else { + return throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s)); + } + } + } + if (start > end) { + return throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s)); + } + if (end > length) { + return throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s)); + } + auto startPtr = castedThis->typedVector() + start; + auto endPtr = castedThis->typedVector() + end; + memset(startPtr, value_uint8, endPtr - startPtr); + return JSValue::encode(castedThis); + } + + { + EnsureStillAliveScope value_ = callFrame->argument(0); + + unsigned int length = castedThis->byteLength(); + unsigned int start = 0; + unsigned int end = length; + WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; + if (callFrame->argumentCount() > 1) { + if (auto start_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) { + start = start_.value(); + } else { + throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s)); + return JSC::JSValue::encode(jsUndefined()); + } + if (callFrame->argumentCount() > 2) { + if (auto end_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) { + end = end_.value(); + } else { + throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s)); + return JSC::JSValue::encode(jsUndefined()); + } + } + + if (callFrame->argumentCount() > 3) { + auto encoding_ = callFrame->uncheckedArgument(3).toString(lexicalGlobalObject); + + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); + } + } + if (start > end) { + throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s)); + return JSC::JSValue::encode(jsUndefined()); + } + if (end > length) { + throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s)); + return JSC::JSValue::encode(jsUndefined()); + } + + auto startPtr = castedThis->typedVector() + start; + + ZigString str = Zig::toString(value.toString(lexicalGlobalObject)); + + Bun__ArrayBuffer buf; + JSC__JSValue__asArrayBuffer_(JSC::JSValue::encode(castedThis), lexicalGlobalObject, + &buf); + Bun__Buffer_fill(lexicalGlobalObject, &buf, &str, start, end, encoding); + + return JSValue::encode(castedThis); + } } static inline JSC::EncodedJSValue jsBufferPrototypeFunction_includesBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBuffer>::ClassParameter castedThis) { diff --git a/src/javascript/jsc/node/buffer.zig b/src/javascript/jsc/node/buffer.zig index a275e8a0d..2b604d594 100644 --- a/src/javascript/jsc/node/buffer.zig +++ b/src/javascript/jsc/node/buffer.zig @@ -13,104 +13,82 @@ const os = std.os; const JSGlobalObject = JSC.JSGlobalObject; const ArgumentsSlice = JSC.Node.ArgumentsSlice; -/// These functions are called in JSBuffer.cpp -/// `CALL_WRITE_FN` is the macro which ultimately calls it -pub const Write = struct { - pub export fn Bun__Buffer__write__BigInt64BE(input: [*]u8, value: i64) void { - std.mem.writeIntBig(i64, input[0..8], value); - } - pub export fn Bun__Buffer__write__BigInt64LE(input: [*]u8, value: i64) void { - std.mem.writeIntLittle(i64, input[0..8], value); - } - pub export fn Bun__Buffer__write__BigUInt64BE(input: [*]u8, value: u64) void { - std.mem.writeIntBig(u64, input[0..8], value); - } - pub export fn Bun__Buffer__write__BigUInt64LE(input: [*]u8, value: u64) void { - std.mem.writeIntLittle(u64, input[0..8], value); - } - pub export fn Bun__Buffer__write__DoubleBE(input: [*]u8, value: f64) void { - std.mem.writeIntBig(u64, input[0..8], @bitCast(u64, value)); - } - pub export fn Bun__Buffer__write__DoubleLE(input: [*]u8, value: f64) void { - std.mem.writeIntLittle(u64, input[0..8], @bitCast(u64, value)); - } - pub export fn Bun__Buffer__write__FloatBE(input: [*]u8, value: f64) void { - std.mem.writeIntBig(i32, input[0..4], @bitCast(i32, @floatCast(f32, value))); - } - pub export fn Bun__Buffer__write__FloatLE(input: [*]u8, value: f64) void { - std.mem.writeIntLittle(i32, input[0..4], @bitCast(i32, @floatCast(f32, value))); - } - pub export fn Bun__Buffer__write__Int16BE(input: [*]u8, value: i32) void { - std.mem.writeIntBig(i16, input[0..2], @intCast(i16, value)); - } - pub export fn Bun__Buffer__write__Int16LE(input: [*]u8, value: i32) void { - std.mem.writeIntLittle(i16, input[0..2], @intCast(i16, value)); - } - pub export fn Bun__Buffer__write__Int32BE(input: [*]u8, value: i32) void { - std.mem.writeIntBig(i32, input[0..4], value); - } - pub export fn Bun__Buffer__write__Int32LE(input: [*]u8, value: i32) void { - std.mem.writeIntLittle(i32, input[0..4], value); - } - pub export fn Bun__Buffer__write__Int64LE(input: [*]u8, value: i64) void { - std.mem.writeIntLittle(i64, input[0..8], value); - } - pub export fn Bun__Buffer__write__Int8(input: [*]u8, value: i32) void { - std.mem.writeIntNative(i8, input[0..1], @truncate(i8, value)); - } - pub export fn Bun__Buffer__write__Int8LE(input: [*]u8, value: i32) void { - std.mem.writeIntLittle(i8, input[0..1], @truncate(i8, value)); - } - pub export fn Bun__Buffer__write__UInt16BE(input: [*]u8, value: i32) void { - std.mem.writeIntBig(u16, input[0..2], @truncate(u16, @bitCast(u32, value))); - } - pub export fn Bun__Buffer__write__UInt16LE(input: [*]u8, value: i32) void { - std.mem.writeIntLittle(u16, input[0..2], @truncate(u16, @bitCast(u32, value))); - } - pub export fn Bun__Buffer__write__UInt32BE(input: [*]u8, value: i32) void { - std.mem.writeIntBig(u32, input[0..4], @bitCast(u32, value)); - } - pub export fn Bun__Buffer__write__UInt32LE(input: [*]u8, value: i32) void { - std.mem.writeIntLittle(u32, input[0..4], @bitCast(u32, value)); - } - pub export fn Bun__Buffer__write__UInt64BE(input: [*]u8, value: u64) void { - std.mem.writeIntBig(u64, input[0..8], value); - } - pub export fn Bun__Buffer__write__UInt64LE(input: [*]u8, value: u64) void { - std.mem.writeIntLittle(u64, input[0..8], value); - } - pub export fn Bun__Buffer__write__UInt8BE(input: [*]u8, value: i32) void { - std.mem.writeIntBig(u8, input[0..1], @bitCast(u8, @truncate(i8, value))); - } - pub export fn Bun__Buffer__write__UInt8LE(input: [*]u8, value: i32) void { - std.mem.writeIntLittle(u8, input[0..1], @bitCast(u8, @truncate(i8, value))); +pub const BufferVectorized = struct { + extern fn memset_pattern16(b: *anyopaque, pattern16: *const anyopaque, len: usize) void; + + pub fn fill( + globalObject: *JSGlobalObject, + this: *JSC.ArrayBuffer, + str: *JSC.ZigString, + start: u32, + end: u32, + encoding: JSC.Node.Encoding, + ) callconv(.C) void { + const allocator = JSC.VirtualMachine.vm.allocator; + var stack_fallback = std.heap.stackFallback(512, allocator); + var stack_fallback_allocator = stack_fallback.get(); + var input_string = str.toSlice(stack_fallback_allocator); + if (input_string.len == 0) return; + + defer input_string.deinit(); + + var buf = this.slice()[start..end]; + + var slice = input_string.slice(); + switch (encoding) { + JSC.Node.Encoding.utf8, + JSC.Node.Encoding.ascii, + JSC.Node.Encoding.latin1, + JSC.Node.Encoding.buffer, + => { + switch (slice.len) { + 0 => unreachable, + 1 => { + @memset(buf.ptr, slice[0], 1); + return; + }, + 2...16 => { + if (comptime Environment.isMac) { + var pattern: [16]u8 = undefined; + var remain: []u8 = pattern[0..]; + + while (remain.len > 0) { + for (slice[0..]) |a| { + remain[0] = a; + remain = remain[1..]; + } + } + + memset_pattern16(buf.ptr, &pattern, buf.len); + return; + } + }, + else => {}, + } + + var in_there = @minimum(slice.len, buf.len); + @memcpy(buf.ptr, slice.ptr, in_there); + if (in_there < slice.len) { + return; + } + + // var ptr = buf.ptr + @as(usize, start) + slice.len; + + // const fill_length = @as(usize, end) - @as(usize, start); + + // // while (in_there < fill_length - in_there) { + // // std.mem.copy(ptr) + // // ptr += in_there; + // // in_there *= 2; + // // } + }, + else => {}, + } } }; comptime { if (!JSC.is_bindgen) { - _ = Write.Bun__Buffer__write__BigInt64BE; - _ = Write.Bun__Buffer__write__BigInt64LE; - _ = Write.Bun__Buffer__write__BigUInt64BE; - _ = Write.Bun__Buffer__write__BigUInt64LE; - _ = Write.Bun__Buffer__write__DoubleBE; - _ = Write.Bun__Buffer__write__DoubleLE; - _ = Write.Bun__Buffer__write__FloatBE; - _ = Write.Bun__Buffer__write__FloatLE; - _ = Write.Bun__Buffer__write__Int16BE; - _ = Write.Bun__Buffer__write__Int16LE; - _ = Write.Bun__Buffer__write__Int32BE; - _ = Write.Bun__Buffer__write__Int32LE; - _ = Write.Bun__Buffer__write__Int64LE; - _ = Write.Bun__Buffer__write__Int8; - _ = Write.Bun__Buffer__write__Int8LE; - _ = Write.Bun__Buffer__write__UInt16BE; - _ = Write.Bun__Buffer__write__UInt16LE; - _ = Write.Bun__Buffer__write__UInt32BE; - _ = Write.Bun__Buffer__write__UInt32LE; - _ = Write.Bun__Buffer__write__UInt64BE; - _ = Write.Bun__Buffer__write__UInt64LE; - _ = Write.Bun__Buffer__write__UInt8BE; - _ = Write.Bun__Buffer__write__UInt8LE; + @export(BufferVectorized, .{ .name = "Bun__Buffer__fill" }); } } |