diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/base64/base64.zig | 24 | ||||
-rw-r--r-- | src/bun.js/bindings/JSBuffer.cpp | 102 | ||||
-rw-r--r-- | src/bun.js/webcore/encoding.zig | 35 | ||||
m--------- | src/deps/uws | 0 |
4 files changed, 125 insertions, 36 deletions
diff --git a/src/base64/base64.zig b/src/base64/base64.zig index be0086c46..a5a94200f 100644 --- a/src/base64/base64.zig +++ b/src/base64/base64.zig @@ -37,24 +37,28 @@ pub fn decodeURLSafe(destination: []u8, source: []const u8) DecodeResult { pub fn encode(destination: []u8, source: []const u8) usize { return zig_base64.standard.Encoder.encode(destination, source).len; + +} + +pub fn decodeLenUpperBound(len: usize) usize { + return zig_base64.standard.Decoder.calcSizeUpperBound(len) catch { + //fallback + return len / 4 * 3; + }; } -/// Given a source string of length len, this returns the amount of -/// memory the destination string should have. -/// -/// remember, this is integer math -/// 3 bytes turn into 4 chars -/// ceiling[len / 3] * 4 -/// -/// pub fn decodeLen(source: anytype) usize { - return (source.len / 4 * 3 + 2); + return zig_base64.standard.Decoder.calcSizeForSlice(source) catch { + //fallback + return source.len / 4 * 3; + }; } pub fn encodeLen(source: anytype) usize { - return (source.len + 2) / 3 * 4; + return zig_base64.standard.Encoder.calcSize(source.len); } + pub const urlsafe = zig_base64.Base64DecoderWithIgnore.init( zig_base64.url_safe_alphabet_chars, null, diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 5b038f3ae..0c393ce05 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -374,18 +374,65 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG return JSValue::encode(jsUndefined()); } - auto arrayBuffer = JSC::ArrayBuffer::tryCreate(length, 1); - if (!arrayBuffer) { - throwOutOfMemoryError(lexicalGlobalObject, throwScope); - return JSValue::encode(jsUndefined()); - } - auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); auto* subclassStructure = globalObject->JSBufferSubclassStructure(); - auto uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, WTFMove(arrayBuffer), 0, length); - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array)); + // fill argument + if(callFrame->argumentCount() > 1){ + auto uint8Array = JSC::JSUint8Array::createUninitialized(lexicalGlobalObject, subclassStructure, length); + + auto value = callFrame->argument(1); + + if (!value.isString()) { + auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF; + + auto value_uint8 = static_cast<uint8_t>(value_); + RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(jsUndefined())); + + auto length = uint8Array->byteLength(); + auto start = 0; + auto end = length; + + auto startPtr = uint8Array->typedVector() + start; + auto endPtr = uint8Array->typedVector() + end; + memset(startPtr, value_uint8, endPtr - startPtr); + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array)); + } + + { + size_t length = uint8Array->byteLength(); + size_t start = 0; + size_t end = length; + WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; + if (callFrame->argumentCount() > 2) { + auto encoding_ = callFrame->uncheckedArgument(2).toString(lexicalGlobalObject); + + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encoding_); + if (!encoded) { + throwTypeError(lexicalGlobalObject, throwScope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + encoding = encoded.value(); + + } + auto startPtr = uint8Array->typedVector() + start; + auto str_ = value.toWTFString(lexicalGlobalObject); + ZigString str = Zig::toZigString(str_); + + Bun__Buffer_fill(&str, startPtr, end - start, encoding); + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array)); + } + } else { + auto arrayBuffer = JSC::ArrayBuffer::tryCreate(length, 1); + if (!arrayBuffer) { + throwOutOfMemoryError(lexicalGlobalObject, throwScope); + return JSValue::encode(jsUndefined()); + } + auto uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, WTFMove(arrayBuffer), 0, length); + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array)); + + } } static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocUnsafeSlowBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) @@ -891,6 +938,8 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF; auto value_uint8 = static_cast<uint8_t>(value_); + RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(jsUndefined())); + auto length = castedThis->byteLength(); auto start = 0; auto end = length; @@ -1363,7 +1412,6 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); return JSC::JSValue::encode(jsUndefined()); } - encoding = encoded.value(); } } @@ -1371,20 +1419,38 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo if (UNLIKELY(length < offset)) { RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::jsNumber(0))); } - + if (callFrame->argumentCount() > 2) { uint32_t arg_len = 0; - arg_len = callFrame->argument(2).toUInt32(lexicalGlobalObject); - length = std::min(arg_len, length - offset); - } + EnsureStillAliveScope arg2 = callFrame->argument(2); + if (arg2.value().isAnyInt()) { + arg_len = arg2.value().toUInt32(lexicalGlobalObject); + length = std::min(arg_len, length); - if (callFrame->argumentCount() > 2) { - std::optional<BufferEncodingType> parsedEncoding = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, callFrame->argument(3)); - if (parsedEncoding.has_value()) { - encoding = parsedEncoding.value(); + if (callFrame->argumentCount() > 3) { + EnsureStillAliveScope arg3 = callFrame->argument(3); + if (arg3.value().isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg3.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + encoding = encoded.value(); + } + } + } else if (arg2.value().isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg2.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); } } + length = length - offset; + auto view = str->tryGetValue(lexicalGlobalObject); int64_t written = 0; @@ -1397,6 +1463,8 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo case WebCore::BufferEncodingType::base64: case WebCore::BufferEncodingType::base64url: case WebCore::BufferEncodingType::hex: { + + if (view.is8Bit()) { written = Bun__encoding__writeLatin1(view.characters8(), view.length(), castedThis->typedVector() + offset, length, static_cast<uint8_t>(encoding)); } else { diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig index 76541e111..4f30aadae 100644 --- a/src/bun.js/webcore/encoding.zig +++ b/src/bun.js/webcore/encoding.zig @@ -860,12 +860,14 @@ pub const Encoder = struct { switch (comptime encoding) { JSC.Node.Encoding.buffer => { + const written = @min(len, to_len); @memcpy(to, input, written); return @intCast(i64, written); }, .latin1, .ascii => { + const written = @min(len, to_len); @memcpy(to, input, written); @@ -887,12 +889,17 @@ pub const Encoder = struct { if (std.mem.isAligned(@ptrToInt(to), @alignOf([*]u16))) { var buf = input[0..len]; + var output = @ptrCast([*]u16, @alignCast(@alignOf(u16), to))[0 .. to_len / 2]; - return strings.copyLatin1IntoUTF16([]u16, output, []const u8, buf).written; + var written = strings.copyLatin1IntoUTF16([]u16, output, []const u8, buf).written; + return written * 2; } else { var buf = input[0..len]; var output = @ptrCast([*]align(1) u16, to)[0 .. to_len / 2]; - return strings.copyLatin1IntoUTF16([]align(1) u16, output, []const u8, buf).written; + + var written = strings.copyLatin1IntoUTF16([]align(1) u16, output, []const u8, buf).written; + return written * 2; + } }, @@ -901,6 +908,7 @@ pub const Encoder = struct { }, JSC.Node.Encoding.base64url => { + var slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.vt}); if (slice.len == 0) return 0; @@ -940,11 +948,11 @@ pub const Encoder = struct { }, JSC.Node.Encoding.hex => { - return len * 2; + return len / 2; }, JSC.Node.Encoding.base64, JSC.Node.Encoding.base64url => { - return bun.base64.encodeLen(input[0..len]); + return bun.base64.decodeLen(input[0..len]); }, // else => return &[_]u8{}; } @@ -958,12 +966,21 @@ pub const Encoder = struct { .utf8 => { return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, input[0..len]).written); }, - // string is already encoded, just need to copy the data - .latin1, JSC.Node.Encoding.ascii, JSC.Node.Encoding.ucs2, JSC.Node.Encoding.buffer, JSC.Node.Encoding.utf16le => { + .latin1, JSC.Node.Encoding.ascii, JSC.Node.Encoding.buffer => { strings.copyU16IntoU8(to[0..to_len], []const u16, input[0..len]); - return @intCast(i64, @min(len, to_len)); }, + // string is already encoded, just need to copy the data + JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => { + var bytes_input_len = len * 2; + var written = @min(bytes_input_len, to_len); + if (written < 2) return 0; + + var fixed_len = (written/2) * 2; + var input_u8 = @ptrCast([*] const u8, input); + strings.copyU16IntoU8(to[0..written], []const u8, input_u8[0..fixed_len]); + return @intCast(i64, written); + }, JSC.Node.Encoding.hex => { return @intCast(i64, strings.decodeHexToBytes(to[0..to_len], u16, input[0..len])); @@ -999,11 +1016,11 @@ pub const Encoder = struct { }, JSC.Node.Encoding.hex => { - return len; + return len / 2; }, JSC.Node.Encoding.base64, JSC.Node.Encoding.base64url => { - return bun.base64.encodeLen(input[0..len]); + return bun.base64.decodeLenUpperBound(len); }, // else => return &[_]u8{}; } diff --git a/src/deps/uws b/src/deps/uws -Subproject a076c28a37ae2ffbcb4e2cec023056b13ba0518 +Subproject 665680ca11e09649b96e665a5eb97edc65cbb65 |