aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/baby_list.zig2
-rw-r--r--src/base64/base64.zig92
-rw-r--r--src/bun.js/bindings/Buffer.h2
-rw-r--r--src/bun.js/bindings/JSBuffer.cpp574
-rw-r--r--src/bun.js/bindings/JSBufferEncodingType.cpp5
-rw-r--r--src/bun.js/bindings/headers-handwritten.h4
-rw-r--r--src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp345
-rw-r--r--src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h81
-rw-r--r--src/bun.js/builtins/js/JSBufferPrototype.js272
-rw-r--r--src/bun.js/node/buffer.zig114
-rw-r--r--src/bun.js/webcore/base64.zig445
-rw-r--r--src/bun.js/webcore/body.zig1
-rw-r--r--src/bun.js/webcore/encoding.zig154
-rw-r--r--src/bun.js/webcore/streams.zig2
-rw-r--r--src/http/websocket_http_client.zig2
-rw-r--r--src/napi/napi.zig14
-rw-r--r--src/string_immutable.zig44
-rw-r--r--src/string_mutable.zig2
18 files changed, 1136 insertions, 1019 deletions
diff --git a/src/baby_list.zig b/src/baby_list.zig
index 0df33b2dc..2ebb383e6 100644
--- a/src/baby_list.zig
+++ b/src/baby_list.zig
@@ -177,7 +177,7 @@ pub fn BabyList(comptime Type: type) type {
const orig_len = list_.items.len;
var slice_ = list_.items.ptr[orig_len..list_.capacity];
- const result = strings.copyUTF16IntoUTF8WithBuffer(slice_, []const u16, remain, trimmed, out_len);
+ const result = strings.copyUTF16IntoUTF8WithBuffer(slice_, []const u16, remain, trimmed, out_len, true);
remain = remain[result.read..];
list_.items.len += @as(usize, result.written);
if (result.read == 0 or result.written == 0) break;
diff --git a/src/base64/base64.zig b/src/base64/base64.zig
index daf5b228e..0cd16fb8c 100644
--- a/src/base64/base64.zig
+++ b/src/base64/base64.zig
@@ -5,34 +5,28 @@ pub const DecodeResult = struct {
fail: bool = false,
};
-pub fn decode(destination: []u8, source: []const u8) DecodeResult {
- var wrote: usize = 0;
- const result = zig_base64.standard.decoderWithIgnore(&[_]u8{
- ' ',
- '\n',
- '\r',
- '\t',
+const mixed_decoder = brk: {
+ var decoder = zig_base64.standard.decoderWithIgnore("\xff \t\r\n" ++ [_]u8{
std.ascii.control_code.vt,
- }).decode(destination, source, &wrote) catch {
- return .{
- .written = wrote,
- .fail = true,
- };
- };
+ std.ascii.control_code.ff,
+ });
- return .{ .written = result, .fail = false };
-}
+ for (zig_base64.url_safe_alphabet_chars[62..], 62..) |c, i| {
+ decoder.decoder.char_to_index[c] = @intCast(u8, i);
+ }
-pub fn decodeURLSafe(destination: []u8, source: []const u8) DecodeResult {
+ break :brk decoder;
+};
+
+pub fn decode(destination: []u8, source: []const u8) DecodeResult {
var wrote: usize = 0;
- const result = urlsafe.decode(destination, source, &wrote) catch {
+ mixed_decoder.decode(destination, source, &wrote) catch {
return .{
.written = wrote,
.fail = true,
};
};
-
- return .{ .written = result, .fail = false };
+ return .{ .written = wrote, .fail = false };
}
pub fn encode(destination: []u8, source: []const u8) usize {
@@ -58,14 +52,6 @@ pub fn encodeLen(source: anytype) usize {
return zig_base64.standard.Encoder.calcSize(source.len);
}
-pub const urlsafe = zig_base64.Base64DecoderWithIgnore.init(
- zig_base64.url_safe_alphabet_chars,
- null,
- "= \t\r\n" ++ [_]u8{ std.ascii.control_code.vt, std.ascii.control_code.ff },
-);
-
-pub const urlsafeEncoder = zig_base64.url_safe_no_pad.Encoder;
-
// This is just std.base64 copy-pasted
// with support for returning how many bytes were decoded
const zig_base64 = struct {
@@ -118,7 +104,7 @@ const zig_base64 = struct {
pub const url_safe_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*;
fn urlSafeBase64DecoderWithIgnore(ignore: []const u8) Base64DecoderWithIgnore {
- return Base64DecoderWithIgnore.init(url_safe_alphabet_chars, null, ignore);
+ return Base64DecoderWithIgnore.init(url_safe_alphabet_chars, '=', ignore);
}
/// URL-safe Base64 codecs, with padding
@@ -316,7 +302,7 @@ const zig_base64 = struct {
/// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding
/// `InvalidPadding` is returned if the input length is not valid.
- pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) Error!usize {
+ pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) usize {
var result = source_len / 4 * 3;
if (decoder_with_ignore.decoder.pad_char == null) {
const leftover = source_len % 4;
@@ -329,7 +315,7 @@ const zig_base64 = struct {
/// Invalid padding results in error.InvalidPadding.
/// Decoding more data than can fit in dest results in error.NoSpaceLeft. See also ::calcSizeUpperBound.
/// Returns the number of bytes written to dest.
- pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8, wrote: *usize) Error!usize {
+ pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8, wrote: *usize) Error!void {
const decoder = &decoder_with_ignore.decoder;
var acc: u12 = 0;
var acc_len: u4 = 0;
@@ -337,16 +323,21 @@ const zig_base64 = struct {
var leftover_idx: ?usize = null;
defer {
- wrote.* = leftover_idx orelse dest_idx;
+ wrote.* = dest_idx;
}
for (source, 0..) |c, src_idx| {
if (decoder_with_ignore.char_is_ignored[c]) continue;
const d = decoder.char_to_index[c];
if (d == Base64Decoder.invalid_char) {
- if (decoder.pad_char == null or c != decoder.pad_char.?) return error.InvalidCharacter;
- leftover_idx = src_idx;
- break;
+ if (decoder.pad_char) |pad_char| {
+ if (c == pad_char) {
+ leftover_idx = src_idx;
+ break;
+ }
+ }
+ if (decoder_with_ignore.char_is_ignored[Base64Decoder.invalid_char]) continue;
+ return error.InvalidCharacter;
}
acc = (acc << 6) + d;
acc_len += 6;
@@ -357,27 +348,26 @@ const zig_base64 = struct {
dest_idx += 1;
}
}
- if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) {
- return error.InvalidPadding;
- }
- const padding_len = acc_len / 2;
- if (leftover_idx == null) {
- if (decoder.pad_char != null and padding_len != 0) return error.InvalidPadding;
- return dest_idx;
- }
- var leftover = source[leftover_idx.?..];
+ if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) return error.InvalidPadding;
+
if (decoder.pad_char) |pad_char| {
- var padding_chars: usize = 0;
- for (leftover) |c| {
- if (decoder_with_ignore.char_is_ignored[c]) continue;
- if (c != pad_char) {
- return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
+ const padding_len = acc_len / 2;
+
+ if (leftover_idx) |idx| {
+ var leftover = source[idx..];
+ var padding_chars: usize = 0;
+ for (leftover) |c| {
+ if (decoder_with_ignore.char_is_ignored[c]) continue;
+ if (c != pad_char) {
+ return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
+ }
+ padding_chars += 1;
}
- padding_chars += 1;
+ if (padding_chars != padding_len) return error.InvalidPadding;
+ } else if (padding_len > 0) {
+ return error.InvalidPadding;
}
- if (padding_chars != padding_len) return error.InvalidPadding;
}
- return dest_idx;
}
};
diff --git a/src/bun.js/bindings/Buffer.h b/src/bun.js/bindings/Buffer.h
index fecc627a1..4f1583513 100644
--- a/src/bun.js/bindings/Buffer.h
+++ b/src/bun.js/bindings/Buffer.h
@@ -16,7 +16,7 @@ extern "C" JSC::EncodedJSValue JSBuffer__bufferFromLength(JSC::JSGlobalObject* l
extern "C" JSC::EncodedJSValue JSBuffer__bufferFromPointerAndLengthAndDeinit(JSC::JSGlobalObject* lexicalGlobalObject, char* ptr, size_t length, void* ctx, JSTypedArrayBytesDeallocator bytesDeallocator);
extern "C" JSC::EncodedJSValue Bun__encoding__toString(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject, Encoding encoding);
extern "C" JSC::EncodedJSValue Bun__encoding__toStringUTF8(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject);
-extern "C" void Bun__Buffer_fill(ZigString*, void*, size_t, WebCore::BufferEncodingType);
+extern "C" bool Bun__Buffer_fill(ZigString*, void*, size_t, WebCore::BufferEncodingType);
namespace WebCore {
diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp
index 2ce07617a..9b3854b95 100644
--- a/src/bun.js/bindings/JSBuffer.cpp
+++ b/src/bun.js/bindings/JSBuffer.cpp
@@ -133,6 +133,35 @@ static int normalizeCompareVal(int val, size_t a_length, size_t b_length)
return val;
}
+static inline uint32_t parseIndex(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ThrowScope& scope, JSValue arg)
+{
+ if (auto num = arg.tryGetAsUint32Index())
+ return num.value();
+
+ if (arg.isNumber())
+ throwRangeError(lexicalGlobalObject, scope, "Invalid array length"_s);
+ else
+ throwTypeError(lexicalGlobalObject, scope, "Expected number"_s);
+
+ return 0;
+}
+
+static inline WebCore::BufferEncodingType parseEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ThrowScope& scope, JSValue arg)
+{
+ if (UNLIKELY(!arg.isString())) {
+ throwTypeError(lexicalGlobalObject, scope, "Expected string"_s);
+ return WebCore::BufferEncodingType::utf8;
+ }
+
+ std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg);
+ if (UNLIKELY(!encoded)) {
+ throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
+ return WebCore::BufferEncodingType::utf8;
+ }
+
+ return encoded.value();
+}
+
namespace WebCore {
using namespace JSC;
@@ -190,8 +219,11 @@ using namespace JSC;
static inline EncodedJSValue writeToBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSArrayBufferView* castedThis, JSString* str, uint32_t offset, uint32_t length, BufferEncodingType encoding)
{
+ if (UNLIKELY(str->length() == 0))
+ return JSC::JSValue::encode(JSC::jsNumber(0));
+
auto view = str->tryGetValue(lexicalGlobalObject);
- int64_t written = 0;
+ size_t written = 0;
switch (encoding) {
case WebCore::BufferEncodingType::utf8:
@@ -358,9 +390,6 @@ static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGl
RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
- if (str->length() == 0)
- return constructBufferEmpty(lexicalGlobalObject);
-
if (arg1 && arg1.isString()) {
std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1);
if (!encoded) {
@@ -371,6 +400,9 @@ static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGl
encoding = encoded.value();
}
+ if (str->length() == 0)
+ return constructBufferEmpty(lexicalGlobalObject);
+
JSC::EncodedJSValue result = constructFromEncoding(lexicalGlobalObject, str, encoding);
RELEASE_AND_RETURN(scope, result);
@@ -380,7 +412,12 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
{
VM& vm = lexicalGlobalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- auto length = callFrame->uncheckedArgument(0).toInt32(lexicalGlobalObject);
+ auto lengthArg = callFrame->uncheckedArgument(0);
+ if (UNLIKELY(!lengthArg.isNumber())) {
+ throwTypeError(lexicalGlobalObject, scope, "Expected number"_s);
+ return JSValue::encode(jsUndefined());
+ }
+ auto length = lengthArg.toInt32(lexicalGlobalObject);
if (length < 0) {
throwRangeError(lexicalGlobalObject, scope, "Invalid array length"_s);
return JSValue::encode(jsUndefined());
@@ -392,10 +429,56 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
// fill argument
if (UNLIKELY(callFrame->argumentCount() > 1)) {
auto* uint8Array = JSC::JSUint8Array::createUninitialized(lexicalGlobalObject, subclassStructure, length);
-
auto value = callFrame->argument(1);
- if (!value.isString()) {
+ if (value.isString()) {
+ size_t length = uint8Array->byteLength();
+ size_t start = 0;
+ size_t end = length;
+ WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
+ if (callFrame->argumentCount() > 2) {
+ EnsureStillAliveScope arg2 = callFrame->uncheckedArgument(2);
+ if (!arg2.value().isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, arg2.value());
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
+ }
+ }
+ auto startPtr = uint8Array->typedVector() + start;
+ auto str_ = value.toWTFString(lexicalGlobalObject);
+ ZigString str = Zig::toZigString(str_);
+
+ if (UNLIKELY(!Bun__Buffer_fill(&str, startPtr, end - start, encoding))) {
+ throwTypeError(lexicalGlobalObject, scope, "Failed to decode value"_s);
+ return JSC::JSValue::encode(jsUndefined());
+ }
+ } else if (auto* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value)) {
+ if (UNLIKELY(view->isDetached())) {
+ throwVMTypeError(lexicalGlobalObject, scope, "Uint8Array is detached"_s);
+ return JSValue::encode(jsUndefined());
+ }
+
+ size_t length = view->byteLength();
+ if (UNLIKELY(length == 0)) {
+ throwTypeError(lexicalGlobalObject, scope, "Buffer cannot be empty"_s);
+ return JSC::JSValue::encode(jsUndefined());
+ }
+
+ auto* start = uint8Array->typedVector();
+ auto* head = start;
+ size_t remain = uint8Array->byteLength();
+ memmove(head, view->vector(), length);
+ remain -= length;
+ head += length;
+ while (remain >= length) {
+ memcpy(head, start, length);
+ remain -= length;
+ head += length;
+ length <<= 1;
+ }
+ if (remain > 0) {
+ memcpy(head, start, remain);
+ }
+ } else {
auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF;
auto value_uint8 = static_cast<uint8_t>(value_);
@@ -408,33 +491,9 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
auto startPtr = uint8Array->typedVector() + start;
auto endPtr = uint8Array->typedVector() + end;
memset(startPtr, value_uint8, endPtr - startPtr);
- RELEASE_AND_RETURN(scope, 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) {
- EnsureStillAliveScope arg2 = callFrame->uncheckedArgument(2);
- 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();
- }
- }
- 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(scope, JSC::JSValue::encode(uint8Array));
- }
+ RELEASE_AND_RETURN(scope, JSC::JSValue::encode(uint8Array));
} else {
auto* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, length);
if (UNLIKELY(!uint8Array)) {
@@ -585,6 +644,10 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::J
throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Buffer (first argument)"_s);
return JSValue::encode(jsUndefined());
}
+ if (UNLIKELY(castedThis->isDetached())) {
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Uint8Array (first argument) is detached"_s);
+ return JSValue::encode(jsUndefined());
+ }
auto buffer = callFrame->uncheckedArgument(1);
JSC::JSArrayBufferView* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(buffer);
@@ -592,13 +655,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::J
throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Buffer (2nd argument)"_s);
return JSValue::encode(jsUndefined());
}
-
if (UNLIKELY(view->isDetached())) {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Uint8Array (first argument) is detached"_s);
- return JSValue::encode(jsUndefined());
- }
-
- if (UNLIKELY(castedThis->isDetached())) {
throwVMTypeError(lexicalGlobalObject, throwScope, "Uint8Array (second argument) is detached"_s);
return JSValue::encode(jsUndefined());
}
@@ -611,43 +668,27 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::J
size_t sourceEndInit = castedThis->byteLength();
size_t sourceEnd = sourceEndInit;
- if (callFrame->argumentCount() > 2) {
- if (auto targetEnd_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) {
- targetStart = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
-
- if (callFrame->argumentCount() > 3) {
- auto targetEndArgument = callFrame->uncheckedArgument(3);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- targetEnd = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 4) {
- auto targetEndArgument = callFrame->uncheckedArgument(4);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- sourceStart = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 5) {
- auto targetEndArgument = callFrame->uncheckedArgument(5);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- sourceEnd = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
+ switch (callFrame->argumentCount()) {
+ default:
+ sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(5));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 5:
+ sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(4));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 4:
+ targetEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 3:
+ targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ break;
+ case 2:
+ case 1:
+ case 0:
+ break;
}
targetStart = std::min(targetStart, std::min(targetEnd, targetEndInit));
@@ -822,43 +863,26 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_compareBody(JSC::JSG
size_t sourceEndInit = castedThis->byteLength();
size_t sourceEnd = sourceEndInit;
- if (callFrame->argumentCount() > 1) {
- if (auto targetEnd_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) {
- targetStart = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
-
- if (callFrame->argumentCount() > 2) {
- auto targetEndArgument = callFrame->uncheckedArgument(2);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- targetEnd = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 3) {
- auto targetEndArgument = callFrame->uncheckedArgument(3);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- sourceStart = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 4) {
- auto targetEndArgument = callFrame->uncheckedArgument(4);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- sourceEnd = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
+ switch (callFrame->argumentCount()) {
+ default:
+ sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(4));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 4:
+ sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 3:
+ targetEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 2:
+ targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ break;
+ case 1:
+ case 0:
+ break;
}
targetStart = std::min(targetStart, std::min(targetEnd, targetEndInit));
@@ -905,31 +929,22 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_copyBody(JSC::JSGlob
size_t sourceEndInit = castedThis->byteLength();
size_t sourceEnd = sourceEndInit;
- if (callFrame->argumentCount() > 1) {
- if (auto targetStart_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) {
- targetStart = targetStart_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
-
- if (callFrame->argumentCount() > 2) {
- if (auto sourceStart_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) {
- sourceStart = sourceStart_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 3) {
- if (auto sourceEnd_ = callFrame->uncheckedArgument(3).tryGetAsUint32Index()) {
- sourceEnd = sourceEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
+ switch (callFrame->argumentCount()) {
+ default:
+ sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 3:
+ sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 2:
+ targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ break;
+ case 1:
+ case 0:
+ break;
}
targetStart = std::min(targetStart, targetEnd);
@@ -993,120 +1008,111 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
}
auto value = callFrame->uncheckedArgument(0);
+ const size_t limit = castedThis->byteLength();
+ size_t start = 0;
+ size_t end = limit;
+ WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
+ JSValue encodingValue = jsUndefined();
+ JSValue offsetValue = jsUndefined();
+ JSValue lengthValue = jsUndefined();
- if (!value.isString()) {
- auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF;
+ switch (callFrame->argumentCount()) {
+ case 4:
+ encodingValue = callFrame->uncheckedArgument(3);
+ FALLTHROUGH;
+ case 3:
+ lengthValue = callFrame->uncheckedArgument(2);
+ FALLTHROUGH;
+ case 2:
+ offsetValue = callFrame->uncheckedArgument(1);
+ FALLTHROUGH;
+ default:
+ break;
+ }
- auto value_uint8 = static_cast<uint8_t>(value_);
+ if (offsetValue.isUndefined() || offsetValue.isString()) {
+ encodingValue = offsetValue;
+ offsetValue = jsUndefined();
+ } else if (lengthValue.isString()) {
+ encodingValue = lengthValue;
+ lengthValue = jsUndefined();
+ }
+
+ if (!encodingValue.isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue);
RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
+ }
- 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, scope, 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, scope, createRangeError(lexicalGlobalObject, "end out of range"_s));
- }
- }
- }
- if (start > end) {
- return throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "start out of range"_s));
- }
- if (end > length) {
- return throwVMError(lexicalGlobalObject, scope, 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);
+ if (!offsetValue.isUndefined()) {
+ start = parseIndex(lexicalGlobalObject, scope, offsetValue);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
}
- {
- EnsureStillAliveScope value_ = callFrame->argument(0);
-
- size_t length = castedThis->byteLength();
- size_t start = 0;
- size_t end = length;
- WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
-
- JSValue encodingValue = jsUndefined();
- JSValue offsetValue = jsUndefined();
- JSValue lengthValue = jsUndefined();
-
- switch (callFrame->argumentCount()) {
- case 4:
- encodingValue = callFrame->uncheckedArgument(3);
- FALLTHROUGH;
- case 3:
- lengthValue = callFrame->uncheckedArgument(2);
- FALLTHROUGH;
- case 2:
- offsetValue = callFrame->uncheckedArgument(1);
- FALLTHROUGH;
- default:
- break;
- }
+ if (!lengthValue.isUndefined()) {
+ end = parseIndex(lexicalGlobalObject, scope, lengthValue);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
+ }
- if (offsetValue.isUndefined() || offsetValue.isString()) {
- encodingValue = offsetValue;
- offsetValue = jsUndefined();
- } else if (lengthValue.isString()) {
- encodingValue = lengthValue;
- lengthValue = jsUndefined();
- }
+ if (start >= end) {
+ RELEASE_AND_RETURN(scope, JSValue::encode(castedThis));
+ }
- if (encodingValue.isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encodingValue);
- if (!encoded) {
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return JSC::JSValue::encode(jsUndefined());
- }
+ if (UNLIKELY(end > limit)) {
+ throwRangeError(lexicalGlobalObject, scope, "end out of range"_s);
+ return JSC::JSValue::encode(jsUndefined());
+ }
- encoding = encoded.value();
- }
+ if (value.isString()) {
+ auto startPtr = castedThis->typedVector() + start;
+ auto str_ = value.toWTFString(lexicalGlobalObject);
+ ZigString str = Zig::toZigString(str_);
- if (!offsetValue.isUndefined()) {
- if (auto offset = offsetValue.tryGetAsUint32Index()) {
- start = offset.value();
- } else {
- throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "start out of range"_s));
- return JSC::JSValue::encode(jsUndefined());
- }
+ if (str.len == 0) {
+ memset(startPtr, 0, end - start);
+ } else if (UNLIKELY(!Bun__Buffer_fill(&str, startPtr, end - start, encoding))) {
+ throwTypeError(lexicalGlobalObject, scope, "Failed to decode value"_s);
+ return JSC::JSValue::encode(jsUndefined());
}
+ } else if (auto* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value)) {
+ auto* startPtr = castedThis->typedVector() + start;
+ auto* head = startPtr;
+ size_t remain = end - start;
- if (!lengthValue.isUndefined()) {
- if (auto length = lengthValue.tryGetAsUint32Index()) {
- end = std::min(static_cast<size_t>(length.value()), end);
- } else {
- throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "end out of range"_s));
- return JSC::JSValue::encode(jsUndefined());
- }
+ if (UNLIKELY(view->isDetached())) {
+ throwVMTypeError(lexicalGlobalObject, scope, "Uint8Array is detached"_s);
+ return JSValue::encode(jsUndefined());
}
- if (start >= end) {
- return JSValue::encode(castedThis);
+ size_t length = view->byteLength();
+ if (UNLIKELY(length == 0)) {
+ throwTypeError(lexicalGlobalObject, scope, "Buffer cannot be empty"_s);
+ return JSC::JSValue::encode(jsUndefined());
}
- auto startPtr = castedThis->typedVector() + start;
- auto str_ = value.toWTFString(lexicalGlobalObject);
- ZigString str = Zig::toZigString(str_);
-
- if (str.len > 0) {
- Bun__Buffer_fill(&str, startPtr, end - start, encoding);
- } else {
- memset(startPtr, 0, end - start);
+ memmove(head, view->vector(), length);
+ remain -= length;
+ head += length;
+ while (remain >= length) {
+ memcpy(head, startPtr, length);
+ remain -= length;
+ head += length;
+ length <<= 1;
+ }
+ if (remain > 0) {
+ memcpy(head, startPtr, remain);
}
+ } else {
+ auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF;
- RELEASE_AND_RETURN(scope, JSValue::encode(castedThis));
+ auto value_uint8 = static_cast<uint8_t>(value_);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
+
+ auto startPtr = castedThis->typedVector() + start;
+ auto endPtr = castedThis->typedVector() + end;
+ memset(startPtr, value_uint8, endPtr - startPtr);
}
+
+ RELEASE_AND_RETURN(scope, JSValue::encode(castedThis));
}
static int64_t indexOf(const uint8_t* thisPtr, int64_t thisLength, const uint8_t* valuePtr, int64_t valueLength, int64_t byteOffset)
@@ -1150,42 +1156,42 @@ static int64_t indexOf(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame*
int64_t byteOffset = last ? length - 1 : 0;
if (callFrame->argumentCount() > 1) {
- auto byteOffset_ = callFrame->uncheckedArgument(1).toNumber(lexicalGlobalObject);
- RETURN_IF_EXCEPTION(scope, -1);
-
- if (std::isnan(byteOffset_) || std::isinf(byteOffset_)) {
- byteOffset = last ? length - 1 : 0;
- } else if (byteOffset_ < 0) {
- byteOffset = length + static_cast<int64_t>(byteOffset_);
+ EnsureStillAliveScope arg1 = callFrame->uncheckedArgument(1);
+ if (arg1.value().isString()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, arg1.value());
+ RETURN_IF_EXCEPTION(scope, -1);
} else {
- byteOffset = static_cast<int64_t>(byteOffset_);
- }
+ auto byteOffset_ = arg1.value().toNumber(lexicalGlobalObject);
+ RETURN_IF_EXCEPTION(scope, -1);
- if (last) {
- if (byteOffset < 0) {
- return -1;
- } else if (byteOffset > length - 1) {
- byteOffset = length - 1;
- }
- } else {
- if (byteOffset <= 0) {
- byteOffset = 0;
- } else if (byteOffset > length - 1) {
- return -1;
+ if (std::isnan(byteOffset_) || std::isinf(byteOffset_)) {
+ byteOffset = last ? length - 1 : 0;
+ } else if (byteOffset_ < 0) {
+ byteOffset = length + static_cast<int64_t>(byteOffset_);
+ } else {
+ byteOffset = static_cast<int64_t>(byteOffset_);
}
- }
- if (callFrame->argumentCount() > 2) {
- EnsureStillAliveScope encodingValue = callFrame->uncheckedArgument(2);
-
- if (encodingValue.value().isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encodingValue.value());
- if (!encoded) {
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return JSC::JSValue::encode(jsUndefined());
+ if (last) {
+ if (byteOffset < 0) {
+ return -1;
+ } else if (byteOffset > length - 1) {
+ byteOffset = length - 1;
+ }
+ } else {
+ if (byteOffset <= 0) {
+ byteOffset = 0;
+ } else if (byteOffset > length - 1) {
+ return -1;
}
+ }
- encoding = encoded.value();
+ if (callFrame->argumentCount() > 2) {
+ EnsureStillAliveScope encodingValue = callFrame->uncheckedArgument(2);
+ if (!encodingValue.value().isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue.value());
+ RETURN_IF_EXCEPTION(scope, -1);
+ }
}
}
}
@@ -1420,6 +1426,7 @@ static inline JSC::EncodedJSValue jsBufferToString(JSC::VM& vm, JSC::JSGlobalObj
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
{
auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto scope = DECLARE_THROW_SCOPE(vm);
uint32_t offset = 0;
uint32_t length = castedThis->length();
uint32_t byteLength = length;
@@ -1436,18 +1443,10 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS
case 3:
case 1: {
EnsureStillAliveScope arg1 = callFrame->uncheckedArgument(0);
- if (arg1.value().isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1.value());
- if (!encoded) {
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return JSC::JSValue::encode(jsUndefined());
- }
-
- encoding = encoded.value();
+ if (!arg1.value().isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, arg1.value());
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
}
-
if (callFrame->argumentCount() == 1)
break;
}
@@ -1456,8 +1455,6 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS
JSC::JSValue arg2 = callFrame->uncheckedArgument(1);
int32_t ioffset = arg2.toInt32(lexicalGlobalObject);
if (ioffset < 0) {
- auto scope = DECLARE_THROW_SCOPE(vm);
-
throwTypeError(lexicalGlobalObject, scope, "Offset must be a positive integer"_s);
return JSC::JSValue::encode(jsUndefined());
}
@@ -1524,9 +1521,6 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo
return JSC::JSValue::encode(jsUndefined());
}
- if (str->length() == 0)
- return JSC::JSValue::encode(JSC::jsNumber(0));
-
JSValue offsetValue = jsUndefined();
JSValue lengthValue = jsUndefined();
JSValue encodingValue = jsUndefined();
@@ -1546,14 +1540,8 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo
}
auto setEncoding = [&]() {
- if (encodingValue.isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encodingValue);
- if (!encoded) {
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return;
- }
-
- encoding = encoded.value();
+ if (!encodingValue.isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue);
}
};
@@ -1570,6 +1558,11 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo
RELEASE_AND_RETURN(scope, writeToBuffer(lexicalGlobalObject, castedThis, str, offset, length, encoding));
}
+ if (UNLIKELY(!offsetValue.isNumber())) {
+ throwTypeError(lexicalGlobalObject, scope, "Invalid offset"_s);
+ return JSC::JSValue::encode(jsUndefined());
+ }
+
int32_t userOffset = offsetValue.toInt32(lexicalGlobalObject);
RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
if (userOffset < 0 || userOffset > max) {
@@ -1845,11 +1838,15 @@ static const HashTableValue JSBufferPrototypeTableValues[]
{ "readInt32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadInt32BECodeGenerator, 1 } },
{ "readInt32LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadInt32LECodeGenerator, 1 } },
{ "readInt8"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadInt8CodeGenerator, 2 } },
+ { "readIntBE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadIntBECodeGenerator, 1 } },
+ { "readIntLE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadIntLECodeGenerator, 1 } },
{ "readUInt16BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt16BECodeGenerator, 1 } },
{ "readUInt16LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt16LECodeGenerator, 1 } },
{ "readUInt32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt32BECodeGenerator, 1 } },
{ "readUInt32LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt32LECodeGenerator, 1 } },
{ "readUInt8"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt8CodeGenerator, 1 } },
+ { "readUIntBE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUIntBECodeGenerator, 1 } },
+ { "readUIntLE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUIntLECodeGenerator, 1 } },
{ "readUint16BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt16BECodeGenerator, 1 } },
{ "readUint16LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt16LECodeGenerator, 1 } },
{ "readUint32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt32BECodeGenerator, 1 } },
@@ -1861,6 +1858,7 @@ static const HashTableValue JSBufferPrototypeTableValues[]
{ "swap32"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_swap32, 0 } },
{ "swap64"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_swap64, 0 } },
{ "toJSON"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeToJSONCodeGenerator, 1 } },
+ { "toLocaleString"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_toString, 4 } },
{ "toString"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_toString, 4 } },
{ "ucs2Slice"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeUcs2SliceCodeGenerator, 2 } },
{ "ucs2Write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeUcs2WriteCodeGenerator, 1 } },
@@ -1886,6 +1884,8 @@ static const HashTableValue JSBufferPrototypeTableValues[]
{ "writeInt32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteInt32BECodeGenerator, 1 } },
{ "writeInt32LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteInt32LECodeGenerator, 1 } },
{ "writeInt8"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteInt8CodeGenerator, 1 } },
+ { "writeIntBE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteIntBECodeGenerator, 1 } },
+ { "writeIntLE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteIntLECodeGenerator, 1 } },
{ "writeUInt16"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16LECodeGenerator, 1 } },
{ "writeUInt16BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16BECodeGenerator, 1 } },
{ "writeUInt16LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16LECodeGenerator, 1 } },
@@ -1893,6 +1893,8 @@ static const HashTableValue JSBufferPrototypeTableValues[]
{ "writeUInt32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt32BECodeGenerator, 1 } },
{ "writeUInt32LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt32LECodeGenerator, 1 } },
{ "writeUInt8"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt8CodeGenerator, 1 } },
+ { "writeUIntBE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUIntBECodeGenerator, 1 } },
+ { "writeUIntLE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUIntLECodeGenerator, 1 } },
{ "writeUint16"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16LECodeGenerator, 1 } },
{ "writeUint16BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16BECodeGenerator, 1 } },
{ "writeUint16LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16LECodeGenerator, 1 } },
diff --git a/src/bun.js/bindings/JSBufferEncodingType.cpp b/src/bun.js/bindings/JSBufferEncodingType.cpp
index 8d99dd4db..dde9e1be2 100644
--- a/src/bun.js/bindings/JSBufferEncodingType.cpp
+++ b/src/bun.js/bindings/JSBufferEncodingType.cpp
@@ -39,7 +39,6 @@ static const NeverDestroyed<String> values[] = {
MAKE_STATIC_STRING_IMPL("base64"),
MAKE_STATIC_STRING_IMPL("base64url"),
MAKE_STATIC_STRING_IMPL("hex"),
- MAKE_STATIC_STRING_IMPL("buffer"),
};
String convertEnumerationToString(BufferEncodingType enumerationValue)
@@ -104,8 +103,6 @@ template<> std::optional<BufferEncodingType> parseEnumeration<BufferEncodingType
case 'B': {
if (WTF::equalIgnoringASCIICase(encoding, "binary"_s))
return BufferEncodingType::latin1; // BINARY is a deprecated alias of LATIN1.
- if (WTF::equalIgnoringASCIICase(encoding, "buffer"_s))
- return BufferEncodingType::buffer;
if (WTF::equalIgnoringASCIICase(encoding, "base64"_s))
return BufferEncodingType::base64;
if (WTF::equalIgnoringASCIICase(encoding, "base64url"_s))
@@ -135,7 +132,7 @@ template<> std::optional<BufferEncodingType> parseEnumeration<BufferEncodingType
}
template<> const char* expectedEnumerationValues<BufferEncodingType>()
{
- return "\"utf8\", \"ucs2\", \"utf16le\", \"latin1\", \"ascii\", \"base64\", \"base64url\", \"hex\", \"buffer\"";
+ return "\"utf8\", \"ucs2\", \"utf16le\", \"latin1\", \"ascii\", \"base64\", \"base64url\", \"hex\"";
}
} // namespace WebCore
diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h
index 8f925e84f..d4e1e72af 100644
--- a/src/bun.js/bindings/headers-handwritten.h
+++ b/src/bun.js/bindings/headers-handwritten.h
@@ -268,8 +268,8 @@ extern "C" const char* Bun__version_sha;
extern "C" void ZigString__free_global(const unsigned char* ptr, size_t len);
-extern "C" int64_t Bun__encoding__writeLatin1(const unsigned char* ptr, size_t len, unsigned char* to, size_t other_len, Encoding encoding);
-extern "C" int64_t Bun__encoding__writeUTF16(const UChar* ptr, size_t len, unsigned char* to, size_t other_len, Encoding encoding);
+extern "C" size_t Bun__encoding__writeLatin1(const unsigned char* ptr, size_t len, unsigned char* to, size_t other_len, Encoding encoding);
+extern "C" size_t Bun__encoding__writeUTF16(const UChar* ptr, size_t len, unsigned char* to, size_t other_len, Encoding encoding);
extern "C" size_t Bun__encoding__byteLengthLatin1(const unsigned char* ptr, size_t len, Encoding encoding);
extern "C" size_t Bun__encoding__byteLengthUTF16(const UChar* ptr, size_t len, Encoding encoding);
diff --git a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
index 8aff61064..1ce441bb6 100644
--- a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
@@ -180,6 +180,146 @@ const char* const s_jsBufferPrototypeReadUInt32BECode =
"})\n" \
;
+const JSC::ConstructAbility s_jsBufferPrototypeReadIntLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeReadIntLECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeReadIntLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeReadIntLECodeLength = 882;
+static const JSC::Intrinsic s_jsBufferPrototypeReadIntLECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeReadIntLECode =
+ "(function (offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " return view.getInt8(offset);\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " return view.getInt16(offset, true);\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " const val = view.getUint16(offset, true) + view.getUint8(offset + 2) * 2 ** 16;\n" \
+ " return val | (val & 2 ** 23) * 0x1fe;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " return view.getInt32(offset, true);\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " const last = view.getUint8(offset + 4);\n" \
+ " return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset, true);\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " const last = view.getUint16(offset + 4, true);\n" \
+ " return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset, true);\n" \
+ " }\n" \
+ " }\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeReadIntBECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeReadIntBECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeReadIntBECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeReadIntBECodeLength = 888;
+static const JSC::Intrinsic s_jsBufferPrototypeReadIntBECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeReadIntBECode =
+ "(function (offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " return view.getInt8(offset);\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " return view.getInt16(offset, false);\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " const val = view.getUint16(offset + 1, false) + view.getUint8(offset) * 2 ** 16;\n" \
+ " return val | (val & 2 ** 23) * 0x1fe;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " return view.getInt32(offset, false);\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " const last = view.getUint8(offset);\n" \
+ " return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset + 1, false);\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " const last = view.getUint16(offset, false);\n" \
+ " return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset + 2, false);\n" \
+ " }\n" \
+ " }\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeReadUIntLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeReadUIntLECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeReadUIntLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeReadUIntLECodeLength = 723;
+static const JSC::Intrinsic s_jsBufferPrototypeReadUIntLECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeReadUIntLECode =
+ "(function (offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " return view.getUint8(offset);\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " return view.getUint16(offset, true);\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " return view.getUint16(offset, true) + view.getUint8(offset + 2) * 2 ** 16;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " return view.getUint32(offset, true);\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " return view.getUint8(offset + 4) * 2 ** 32 + view.getUint32(offset, true);\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " return view.getUint16(offset + 4, true) * 2 ** 32 + view.getUint32(offset, true);\n" \
+ " }\n" \
+ " }\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeReadUIntBECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeReadUIntBECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeReadUIntBECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeReadUIntBECodeLength = 842;
+static const JSC::Intrinsic s_jsBufferPrototypeReadUIntBECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeReadUIntBECode =
+ "(function (offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " return view.getUint8(offset);\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " return view.getUint16(offset, false);\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " return view.getUint16(offset + 1, false) + view.getUint8(offset) * 2 ** 16;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " return view.getUint32(offset, false);\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " const last = view.getUint8(offset);\n" \
+ " return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset + 1, false);\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " const last = view.getUint16(offset, false);\n" \
+ " return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset + 2, false);\n" \
+ " }\n" \
+ " }\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ "})\n" \
+;
+
const JSC::ConstructAbility s_jsBufferPrototypeReadFloatLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeReadFloatLECodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeReadFloatLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
@@ -406,6 +546,186 @@ const char* const s_jsBufferPrototypeWriteUInt32BECode =
"})\n" \
;
+const JSC::ConstructAbility s_jsBufferPrototypeWriteIntLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeWriteIntLECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeWriteIntLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeWriteIntLECodeLength = 949;
+static const JSC::Intrinsic s_jsBufferPrototypeWriteIntLECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeWriteIntLECode =
+ "(function (value, offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " view.setInt8(offset, value);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " view.setInt16(offset, value, true);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " view.setUint16(offset, value & 0xFFFF, true);\n" \
+ " view.setInt8(offset + 2, Math.floor(value * 2 ** -16));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " view.setInt32(offset, value, true);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " view.setUint32(offset, value | 0, true);\n" \
+ " view.setInt8(offset + 4, Math.floor(value * 2 ** -32));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " view.setUint32(offset, value | 0, true);\n" \
+ " view.setInt16(offset + 4, Math.floor(value * 2 ** -32), true);\n" \
+ " break;\n" \
+ " }\n" \
+ " default: {\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ " }\n" \
+ " }\n" \
+ " return offset + byteLength;\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeWriteIntBECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeWriteIntBECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeWriteIntBECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeWriteIntBECodeLength = 955;
+static const JSC::Intrinsic s_jsBufferPrototypeWriteIntBECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeWriteIntBECode =
+ "(function (value, offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " view.setInt8(offset, value);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " view.setInt16(offset, value, false);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " view.setUint16(offset + 1, value & 0xFFFF, false);\n" \
+ " view.setInt8(offset, Math.floor(value * 2 ** -16));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " view.setInt32(offset, value, false);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " view.setUint32(offset + 1, value | 0, false);\n" \
+ " view.setInt8(offset, Math.floor(value * 2 ** -32));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " view.setUint32(offset + 2, value | 0, false);\n" \
+ " view.setInt16(offset, Math.floor(value * 2 ** -32), false);\n" \
+ " break;\n" \
+ " }\n" \
+ " default: {\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ " }\n" \
+ " }\n" \
+ " return offset + byteLength;\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeWriteUIntLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeWriteUIntLECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUIntLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeWriteUIntLECodeLength = 955;
+static const JSC::Intrinsic s_jsBufferPrototypeWriteUIntLECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeWriteUIntLECode =
+ "(function (value, offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " view.setUint8(offset, value);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " view.setUint16(offset, value, true);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " view.setUint16(offset, value & 0xFFFF, true);\n" \
+ " view.setUint8(offset + 2, Math.floor(value * 2 ** -16));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " view.setUint32(offset, value, true);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " view.setUint32(offset, value | 0, true);\n" \
+ " view.setUint8(offset + 4, Math.floor(value * 2 ** -32));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " view.setUint32(offset, value | 0, true);\n" \
+ " view.setUint16(offset + 4, Math.floor(value * 2 ** -32), true);\n" \
+ " break;\n" \
+ " }\n" \
+ " default: {\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ " }\n" \
+ " }\n" \
+ " return offset + byteLength;\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeWriteUIntBECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeWriteUIntBECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUIntBECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeWriteUIntBECodeLength = 961;
+static const JSC::Intrinsic s_jsBufferPrototypeWriteUIntBECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeWriteUIntBECode =
+ "(function (value, offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " view.setUint8(offset, value);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " view.setUint16(offset, value, false);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " view.setUint16(offset + 1, value & 0xFFFF, false);\n" \
+ " view.setUint8(offset, Math.floor(value * 2 ** -16));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " view.setUint32(offset, value, false);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " view.setUint32(offset + 1, value | 0, false);\n" \
+ " view.setUint8(offset, Math.floor(value * 2 ** -32));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " view.setUint32(offset + 2, value | 0, false);\n" \
+ " view.setUint16(offset, Math.floor(value * 2 ** -32), false);\n" \
+ " break;\n" \
+ " }\n" \
+ " default: {\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ " }\n" \
+ " }\n" \
+ " return offset + byteLength;\n" \
+ "})\n" \
+;
+
const JSC::ConstructAbility s_jsBufferPrototypeWriteFloatLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeWriteFloatLECodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeWriteFloatLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
@@ -719,7 +1039,7 @@ const char* const s_jsBufferPrototypeToJSONCode =
const JSC::ConstructAbility s_jsBufferPrototypeSliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeSliceCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeSliceCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_jsBufferPrototypeSliceCodeLength = 612;
+const int s_jsBufferPrototypeSliceCodeLength = 613;
static const JSC::Intrinsic s_jsBufferPrototypeSliceCodeIntrinsic = JSC::NoIntrinsic;
const char* const s_jsBufferPrototypeSliceCode =
"(function (start, end) {\n" \
@@ -741,7 +1061,7 @@ const char* const s_jsBufferPrototypeSliceCode =
" }\n" \
"\n" \
" var start_ = adjustOffset(start, byteLength);\n" \
- " var end_ = end !== undefined ? adjustOffset(end, byteLength) : byteLength;\n" \
+ " var end_ = end !== @undefined ? adjustOffset(end, byteLength) : byteLength;\n" \
" return new Buffer(buffer, byteOffset + start_, end_ > start_ ? (end_ - start_) : 0);\n" \
"})\n" \
;
@@ -749,37 +1069,24 @@ const char* const s_jsBufferPrototypeSliceCode =
const JSC::ConstructAbility s_jsBufferPrototypeParentCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeParentCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeParentCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_jsBufferPrototypeParentCodeLength = 57;
+const int s_jsBufferPrototypeParentCodeLength = 114;
static const JSC::Intrinsic s_jsBufferPrototypeParentCodeIntrinsic = JSC::NoIntrinsic;
const char* const s_jsBufferPrototypeParentCode =
"(function () {\n" \
" \"use strict\";\n" \
- " return this?.buffer;\n" \
+ " return @isObject(this) && this instanceof @Buffer ? this.buffer : @undefined;\n" \
"})\n" \
;
const JSC::ConstructAbility s_jsBufferPrototypeOffsetCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeOffsetCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeOffsetCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_jsBufferPrototypeOffsetCodeLength = 61;
+const int s_jsBufferPrototypeOffsetCodeLength = 118;
static const JSC::Intrinsic s_jsBufferPrototypeOffsetCodeIntrinsic = JSC::NoIntrinsic;
const char* const s_jsBufferPrototypeOffsetCode =
"(function () {\n" \
" \"use strict\";\n" \
- " return this?.byteOffset;\n" \
- "})\n" \
-;
-
-const JSC::ConstructAbility s_jsBufferPrototypeInitializeBunBufferCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
-const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeConstructorKind = JSC::ConstructorKind::None;
-const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBufferCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_jsBufferPrototypeInitializeBunBufferCodeLength = 45;
-static const JSC::Intrinsic s_jsBufferPrototypeInitializeBunBufferCodeIntrinsic = JSC::NoIntrinsic;
-const char* const s_jsBufferPrototypeInitializeBunBufferCode =
- "(function (parameters)\n" \
- "{\n" \
- " \"use strict\";\n" \
- "\n" \
+ " return @isObject(this) && this instanceof @Buffer ? this.byteOffset : @undefined;\n" \
"})\n" \
;
diff --git a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
index f7a3364de..60c00bedf 100644
--- a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
+++ b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
@@ -102,6 +102,26 @@ extern const int s_jsBufferPrototypeReadUInt32BECodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeReadUInt32BECodeConstructAbility;
extern const JSC::ConstructorKind s_jsBufferPrototypeReadUInt32BECodeConstructorKind;
extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadUInt32BECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeReadIntLECode;
+extern const int s_jsBufferPrototypeReadIntLECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeReadIntLECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeReadIntLECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadIntLECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeReadIntBECode;
+extern const int s_jsBufferPrototypeReadIntBECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeReadIntBECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeReadIntBECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadIntBECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeReadUIntLECode;
+extern const int s_jsBufferPrototypeReadUIntLECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeReadUIntLECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeReadUIntLECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadUIntLECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeReadUIntBECode;
+extern const int s_jsBufferPrototypeReadUIntBECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeReadUIntBECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeReadUIntBECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadUIntBECodeImplementationVisibility;
extern const char* const s_jsBufferPrototypeReadFloatLECode;
extern const int s_jsBufferPrototypeReadFloatLECodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeReadFloatLECodeConstructAbility;
@@ -192,6 +212,26 @@ extern const int s_jsBufferPrototypeWriteUInt32BECodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeWriteUInt32BECodeConstructAbility;
extern const JSC::ConstructorKind s_jsBufferPrototypeWriteUInt32BECodeConstructorKind;
extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUInt32BECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeWriteIntLECode;
+extern const int s_jsBufferPrototypeWriteIntLECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeWriteIntLECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeWriteIntLECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteIntLECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeWriteIntBECode;
+extern const int s_jsBufferPrototypeWriteIntBECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeWriteIntBECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeWriteIntBECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteIntBECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeWriteUIntLECode;
+extern const int s_jsBufferPrototypeWriteUIntLECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeWriteUIntLECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeWriteUIntLECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUIntLECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeWriteUIntBECode;
+extern const int s_jsBufferPrototypeWriteUIntBECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeWriteUIntBECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeWriteUIntBECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUIntBECodeImplementationVisibility;
extern const char* const s_jsBufferPrototypeWriteFloatLECode;
extern const int s_jsBufferPrototypeWriteFloatLECodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeWriteFloatLECodeConstructAbility;
@@ -332,11 +372,6 @@ extern const int s_jsBufferPrototypeOffsetCodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeOffsetCodeConstructAbility;
extern const JSC::ConstructorKind s_jsBufferPrototypeOffsetCodeConstructorKind;
extern const JSC::ImplementationVisibility s_jsBufferPrototypeOffsetCodeImplementationVisibility;
-extern const char* const s_jsBufferPrototypeInitializeBunBufferCode;
-extern const int s_jsBufferPrototypeInitializeBunBufferCodeLength;
-extern const JSC::ConstructAbility s_jsBufferPrototypeInitializeBunBufferCodeConstructAbility;
-extern const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeConstructorKind;
-extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBufferCodeImplementationVisibility;
#define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_DATA(macro) \
macro(setBigUint64, jsBufferPrototypeSetBigUint64, 3) \
@@ -350,6 +385,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(readInt32BE, jsBufferPrototypeReadInt32BE, 1) \
macro(readUInt32LE, jsBufferPrototypeReadUInt32LE, 1) \
macro(readUInt32BE, jsBufferPrototypeReadUInt32BE, 1) \
+ macro(readIntLE, jsBufferPrototypeReadIntLE, 2) \
+ macro(readIntBE, jsBufferPrototypeReadIntBE, 2) \
+ macro(readUIntLE, jsBufferPrototypeReadUIntLE, 2) \
+ macro(readUIntBE, jsBufferPrototypeReadUIntBE, 2) \
macro(readFloatLE, jsBufferPrototypeReadFloatLE, 1) \
macro(readFloatBE, jsBufferPrototypeReadFloatBE, 1) \
macro(readDoubleLE, jsBufferPrototypeReadDoubleLE, 1) \
@@ -368,6 +407,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(writeInt32BE, jsBufferPrototypeWriteInt32BE, 2) \
macro(writeUInt32LE, jsBufferPrototypeWriteUInt32LE, 2) \
macro(writeUInt32BE, jsBufferPrototypeWriteUInt32BE, 2) \
+ macro(writeIntLE, jsBufferPrototypeWriteIntLE, 3) \
+ macro(writeIntBE, jsBufferPrototypeWriteIntBE, 3) \
+ macro(writeUIntLE, jsBufferPrototypeWriteUIntLE, 3) \
+ macro(writeUIntBE, jsBufferPrototypeWriteUIntBE, 3) \
macro(writeFloatLE, jsBufferPrototypeWriteFloatLE, 2) \
macro(writeFloatBE, jsBufferPrototypeWriteFloatBE, 2) \
macro(writeDoubleLE, jsBufferPrototypeWriteDoubleLE, 2) \
@@ -396,7 +439,6 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(slice, jsBufferPrototypeSlice, 2) \
macro(parent, jsBufferPrototypeParent, 0) \
macro(offset, jsBufferPrototypeOffset, 0) \
- macro(initializeBunBuffer, jsBufferPrototypeInitializeBunBuffer, 1) \
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_SETBIGUINT64 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READINT8 1
@@ -409,6 +451,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READINT32BE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READUINT32LE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READUINT32BE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READINTLE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READINTBE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READUINTLE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READUINTBE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READFLOATLE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READFLOATBE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READDOUBLELE 1
@@ -427,6 +473,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEINT32BE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEUINT32LE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEUINT32BE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEINTLE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEINTBE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEUINTLE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEUINTBE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEFLOATLE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEFLOATBE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEDOUBLELE 1
@@ -455,7 +505,6 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_SLICE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_PARENT 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_OFFSET 1
-#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_INITIALIZEBUNBUFFER 1
#define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_CODE(macro) \
macro(jsBufferPrototypeSetBigUint64Code, setBigUint64, ASCIILiteral(), s_jsBufferPrototypeSetBigUint64CodeLength) \
@@ -469,6 +518,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(jsBufferPrototypeReadInt32BECode, readInt32BE, ASCIILiteral(), s_jsBufferPrototypeReadInt32BECodeLength) \
macro(jsBufferPrototypeReadUInt32LECode, readUInt32LE, ASCIILiteral(), s_jsBufferPrototypeReadUInt32LECodeLength) \
macro(jsBufferPrototypeReadUInt32BECode, readUInt32BE, ASCIILiteral(), s_jsBufferPrototypeReadUInt32BECodeLength) \
+ macro(jsBufferPrototypeReadIntLECode, readIntLE, ASCIILiteral(), s_jsBufferPrototypeReadIntLECodeLength) \
+ macro(jsBufferPrototypeReadIntBECode, readIntBE, ASCIILiteral(), s_jsBufferPrototypeReadIntBECodeLength) \
+ macro(jsBufferPrototypeReadUIntLECode, readUIntLE, ASCIILiteral(), s_jsBufferPrototypeReadUIntLECodeLength) \
+ macro(jsBufferPrototypeReadUIntBECode, readUIntBE, ASCIILiteral(), s_jsBufferPrototypeReadUIntBECodeLength) \
macro(jsBufferPrototypeReadFloatLECode, readFloatLE, ASCIILiteral(), s_jsBufferPrototypeReadFloatLECodeLength) \
macro(jsBufferPrototypeReadFloatBECode, readFloatBE, ASCIILiteral(), s_jsBufferPrototypeReadFloatBECodeLength) \
macro(jsBufferPrototypeReadDoubleLECode, readDoubleLE, ASCIILiteral(), s_jsBufferPrototypeReadDoubleLECodeLength) \
@@ -487,6 +540,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(jsBufferPrototypeWriteInt32BECode, writeInt32BE, ASCIILiteral(), s_jsBufferPrototypeWriteInt32BECodeLength) \
macro(jsBufferPrototypeWriteUInt32LECode, writeUInt32LE, ASCIILiteral(), s_jsBufferPrototypeWriteUInt32LECodeLength) \
macro(jsBufferPrototypeWriteUInt32BECode, writeUInt32BE, ASCIILiteral(), s_jsBufferPrototypeWriteUInt32BECodeLength) \
+ macro(jsBufferPrototypeWriteIntLECode, writeIntLE, ASCIILiteral(), s_jsBufferPrototypeWriteIntLECodeLength) \
+ macro(jsBufferPrototypeWriteIntBECode, writeIntBE, ASCIILiteral(), s_jsBufferPrototypeWriteIntBECodeLength) \
+ macro(jsBufferPrototypeWriteUIntLECode, writeUIntLE, ASCIILiteral(), s_jsBufferPrototypeWriteUIntLECodeLength) \
+ macro(jsBufferPrototypeWriteUIntBECode, writeUIntBE, ASCIILiteral(), s_jsBufferPrototypeWriteUIntBECodeLength) \
macro(jsBufferPrototypeWriteFloatLECode, writeFloatLE, ASCIILiteral(), s_jsBufferPrototypeWriteFloatLECodeLength) \
macro(jsBufferPrototypeWriteFloatBECode, writeFloatBE, ASCIILiteral(), s_jsBufferPrototypeWriteFloatBECodeLength) \
macro(jsBufferPrototypeWriteDoubleLECode, writeDoubleLE, ASCIILiteral(), s_jsBufferPrototypeWriteDoubleLECodeLength) \
@@ -515,7 +572,6 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(jsBufferPrototypeSliceCode, slice, ASCIILiteral(), s_jsBufferPrototypeSliceCodeLength) \
macro(jsBufferPrototypeParentCode, parent, "get parent"_s, s_jsBufferPrototypeParentCodeLength) \
macro(jsBufferPrototypeOffsetCode, offset, "get offset"_s, s_jsBufferPrototypeOffsetCodeLength) \
- macro(jsBufferPrototypeInitializeBunBufferCode, initializeBunBuffer, ASCIILiteral(), s_jsBufferPrototypeInitializeBunBufferCodeLength) \
#define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_FUNCTION_NAME(macro) \
macro(asciiSlice) \
@@ -526,7 +582,6 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(base64urlWrite) \
macro(hexSlice) \
macro(hexWrite) \
- macro(initializeBunBuffer) \
macro(latin1Slice) \
macro(latin1Write) \
macro(offset) \
@@ -544,11 +599,15 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(readInt32BE) \
macro(readInt32LE) \
macro(readInt8) \
+ macro(readIntBE) \
+ macro(readIntLE) \
macro(readUInt16BE) \
macro(readUInt16LE) \
macro(readUInt32BE) \
macro(readUInt32LE) \
macro(readUInt8) \
+ macro(readUIntBE) \
+ macro(readUIntLE) \
macro(setBigUint64) \
macro(slice) \
macro(toJSON) \
@@ -571,11 +630,15 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(writeInt32BE) \
macro(writeInt32LE) \
macro(writeInt8) \
+ macro(writeIntBE) \
+ macro(writeIntLE) \
macro(writeUInt16BE) \
macro(writeUInt16LE) \
macro(writeUInt32BE) \
macro(writeUInt32LE) \
macro(writeUInt8) \
+ macro(writeUIntBE) \
+ macro(writeUIntLE) \
#define DECLARE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \
JSC::FunctionExecutable* codeName##Generator(JSC::VM&);
diff --git a/src/bun.js/builtins/js/JSBufferPrototype.js b/src/bun.js/builtins/js/JSBufferPrototype.js
index 827e613d8..32aebb3f2 100644
--- a/src/bun.js/builtins/js/JSBufferPrototype.js
+++ b/src/bun.js/builtins/js/JSBufferPrototype.js
@@ -73,6 +73,116 @@ function readUInt32BE(offset) {
"use strict";
return (this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getUint32(offset, false);
}
+
+function readIntLE(offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ return view.getInt8(offset);
+ }
+ case 2: {
+ return view.getInt16(offset, true);
+ }
+ case 3: {
+ const val = view.getUint16(offset, true) + view.getUint8(offset + 2) * 2 ** 16;
+ return val | (val & 2 ** 23) * 0x1fe;
+ }
+ case 4: {
+ return view.getInt32(offset, true);
+ }
+ case 5: {
+ const last = view.getUint8(offset + 4);
+ return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset, true);
+ }
+ case 6: {
+ const last = view.getUint16(offset + 4, true);
+ return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset, true);
+ }
+ }
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+}
+function readIntBE(offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ return view.getInt8(offset);
+ }
+ case 2: {
+ return view.getInt16(offset, false);
+ }
+ case 3: {
+ const val = view.getUint16(offset + 1, false) + view.getUint8(offset) * 2 ** 16;
+ return val | (val & 2 ** 23) * 0x1fe;
+ }
+ case 4: {
+ return view.getInt32(offset, false);
+ }
+ case 5: {
+ const last = view.getUint8(offset);
+ return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset + 1, false);
+ }
+ case 6: {
+ const last = view.getUint16(offset, false);
+ return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset + 2, false);
+ }
+ }
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+}
+function readUIntLE(offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ return view.getUint8(offset);
+ }
+ case 2: {
+ return view.getUint16(offset, true);
+ }
+ case 3: {
+ return view.getUint16(offset, true) + view.getUint8(offset + 2) * 2 ** 16;
+ }
+ case 4: {
+ return view.getUint32(offset, true);
+ }
+ case 5: {
+ return view.getUint8(offset + 4) * 2 ** 32 + view.getUint32(offset, true);
+ }
+ case 6: {
+ return view.getUint16(offset + 4, true) * 2 ** 32 + view.getUint32(offset, true);
+ }
+ }
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+}
+function readUIntBE(offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ return view.getUint8(offset);
+ }
+ case 2: {
+ return view.getUint16(offset, false);
+ }
+ case 3: {
+ return view.getUint16(offset + 1, false) + view.getUint8(offset) * 2 ** 16;
+ }
+ case 4: {
+ return view.getUint32(offset, false);
+ }
+ case 5: {
+ const last = view.getUint8(offset);
+ return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset + 1, false);
+ }
+ case 6: {
+ const last = view.getUint16(offset, false);
+ return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset + 2, false);
+ }
+ }
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+}
+
function readFloatLE(offset) {
"use strict";
return (this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getFloat32(offset, true);
@@ -105,6 +215,7 @@ function readBigUInt64BE(offset) {
"use strict";
return (this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getBigUint64(offset, false);
}
+
function writeInt8(value, offset) {
"use strict";
(this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setInt8(offset, value);
@@ -156,6 +267,155 @@ function writeUInt32BE(value, offset) {
return offset + 4;
}
+function writeIntLE(value, offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ view.setInt8(offset, value);
+ break;
+ }
+ case 2: {
+ view.setInt16(offset, value, true);
+ break;
+ }
+ case 3: {
+ view.setUint16(offset, value & 0xFFFF, true);
+ view.setInt8(offset + 2, Math.floor(value * 2 ** -16));
+ break;
+ }
+ case 4: {
+ view.setInt32(offset, value, true);
+ break;
+ }
+ case 5: {
+ view.setUint32(offset, value | 0, true);
+ view.setInt8(offset + 4, Math.floor(value * 2 ** -32));
+ break;
+ }
+ case 6: {
+ view.setUint32(offset, value | 0, true);
+ view.setInt16(offset + 4, Math.floor(value * 2 ** -32), true);
+ break;
+ }
+ default: {
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+ }
+ }
+ return offset + byteLength;
+}
+function writeIntBE(value, offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ view.setInt8(offset, value);
+ break;
+ }
+ case 2: {
+ view.setInt16(offset, value, false);
+ break;
+ }
+ case 3: {
+ view.setUint16(offset + 1, value & 0xFFFF, false);
+ view.setInt8(offset, Math.floor(value * 2 ** -16));
+ break;
+ }
+ case 4: {
+ view.setInt32(offset, value, false);
+ break;
+ }
+ case 5: {
+ view.setUint32(offset + 1, value | 0, false);
+ view.setInt8(offset, Math.floor(value * 2 ** -32));
+ break;
+ }
+ case 6: {
+ view.setUint32(offset + 2, value | 0, false);
+ view.setInt16(offset, Math.floor(value * 2 ** -32), false);
+ break;
+ }
+ default: {
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+ }
+ }
+ return offset + byteLength;
+}
+function writeUIntLE(value, offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ view.setUint8(offset, value);
+ break;
+ }
+ case 2: {
+ view.setUint16(offset, value, true);
+ break;
+ }
+ case 3: {
+ view.setUint16(offset, value & 0xFFFF, true);
+ view.setUint8(offset + 2, Math.floor(value * 2 ** -16));
+ break;
+ }
+ case 4: {
+ view.setUint32(offset, value, true);
+ break;
+ }
+ case 5: {
+ view.setUint32(offset, value | 0, true);
+ view.setUint8(offset + 4, Math.floor(value * 2 ** -32));
+ break;
+ }
+ case 6: {
+ view.setUint32(offset, value | 0, true);
+ view.setUint16(offset + 4, Math.floor(value * 2 ** -32), true);
+ break;
+ }
+ default: {
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+ }
+ }
+ return offset + byteLength;
+}
+function writeUIntBE(value, offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ view.setUint8(offset, value);
+ break;
+ }
+ case 2: {
+ view.setUint16(offset, value, false);
+ break;
+ }
+ case 3: {
+ view.setUint16(offset + 1, value & 0xFFFF, false);
+ view.setUint8(offset, Math.floor(value * 2 ** -16));
+ break;
+ }
+ case 4: {
+ view.setUint32(offset, value, false);
+ break;
+ }
+ case 5: {
+ view.setUint32(offset + 1, value | 0, false);
+ view.setUint8(offset, Math.floor(value * 2 ** -32));
+ break;
+ }
+ case 6: {
+ view.setUint32(offset + 2, value | 0, false);
+ view.setUint16(offset, Math.floor(value * 2 ** -32), false);
+ break;
+ }
+ default: {
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+ }
+ }
+ return offset + byteLength;
+}
+
function writeFloatLE(value, offset) {
"use strict";
(this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setFloat32(offset, value, true);
@@ -296,24 +556,18 @@ function slice(start, end) {
}
var start_ = adjustOffset(start, byteLength);
- var end_ = end !== undefined ? adjustOffset(end, byteLength) : byteLength;
+ var end_ = end !== @undefined ? adjustOffset(end, byteLength) : byteLength;
return new Buffer(buffer, byteOffset + start_, end_ > start_ ? (end_ - start_) : 0);
}
@getter
function parent() {
"use strict";
- return this?.buffer;
+ return @isObject(this) && this instanceof @Buffer ? this.buffer : @undefined;
}
@getter
function offset() {
"use strict";
- return this?.byteOffset;
-}
-
-function initializeBunBuffer(parameters)
-{
- "use strict";
-
+ return @isObject(this) && this instanceof @Buffer ? this.byteOffset : @undefined;
}
diff --git a/src/bun.js/node/buffer.zig b/src/bun.js/node/buffer.zig
index 5a7d64955..f3cc3c2c2 100644
--- a/src/bun.js/node/buffer.zig
+++ b/src/bun.js/node/buffer.zig
@@ -1,96 +1,72 @@
-const std = @import("std");
const bun = @import("bun");
-const strings = bun.strings;
-const string = bun.string;
-const AsyncIO = @import("bun").AsyncIO;
-const JSC = @import("bun").JSC;
-const PathString = JSC.PathString;
-const Environment = bun.Environment;
-const C = bun.C;
-const Syscall = @import("./syscall.zig");
-const os = std.os;
-
-const JSGlobalObject = JSC.JSGlobalObject;
-const ArgumentsSlice = JSC.Node.ArgumentsSlice;
+const JSC = bun.JSC;
+const Encoder = JSC.WebCore.Encoder;
pub const BufferVectorized = struct {
- extern fn memset_pattern16(b: *anyopaque, pattern16: *const anyopaque, len: usize) void;
-
pub fn fill(
str: *JSC.ZigString,
buf_ptr: [*]u8,
fill_length: usize,
encoding: JSC.Node.Encoding,
- ) callconv(.C) void {
- if (str.len == 0) return;
+ ) callconv(.C) bool {
+ if (str.len == 0) return true;
var buf = buf_ptr[0..fill_length];
const written = switch (encoding) {
- JSC.Node.Encoding.utf8 => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.utf8, true)
+ .utf8 => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .utf8, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.utf8),
- JSC.Node.Encoding.ascii => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.ascii, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .utf8),
+ .ascii => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .ascii, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.ascii),
- JSC.Node.Encoding.latin1 => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.latin1, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .ascii),
+ .latin1 => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .latin1, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.latin1),
- JSC.Node.Encoding.buffer => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.buffer, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .latin1),
+ .buffer => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .buffer, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.buffer),
- JSC.Node.Encoding.utf16le,
- JSC.Node.Encoding.ucs2,
- => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.utf16le, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .buffer),
+ .utf16le, .ucs2 => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .utf16le, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.utf16le),
- JSC.Node.Encoding.base64 => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.base64, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .utf16le),
+ .base64 => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .base64, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.base64),
- JSC.Node.Encoding.base64url => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.base64url, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .base64),
+ .base64url => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .base64url, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.base64url),
- JSC.Node.Encoding.hex => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.hex, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .base64url),
+ .hex => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .hex, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.hex),
- };
-
- if (written <= 0) {
- return;
- }
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .hex),
+ } catch return false;
- var contents = buf[0..@intCast(usize, written)];
- buf = buf[@intCast(usize, written)..];
+ switch (written) {
+ 0 => {},
+ 1 => @memset(buf.ptr, buf[0], buf.len),
+ else => {
+ var contents = buf[0..written];
+ buf = buf[written..];
- if (contents.len == 1) {
- @memset(buf.ptr, contents[0], buf.len);
- return;
- }
-
- const minimum_contents = contents;
- while (buf.len >= contents.len) {
- const min_len = @min(contents.len, buf.len);
- bun.copy(u8, buf, contents[0..min_len]);
- if (buf.len <= contents.len) {
- break;
- }
- buf = buf[min_len..];
- contents.len *= 2;
- }
+ while (buf.len >= contents.len) {
+ bun.copy(u8, buf, contents);
+ buf = buf[contents.len..];
+ contents.len *= 2;
+ }
- while (buf.len > 0) {
- const to_fill = @min(minimum_contents.len, buf.len);
- bun.copy(u8, buf, minimum_contents[0..to_fill]);
- buf = buf[to_fill..];
+ if (buf.len > 0) {
+ bun.copy(u8, buf, contents[0..buf.len]);
+ }
+ },
}
+ return true;
}
};
diff --git a/src/bun.js/webcore/base64.zig b/src/bun.js/webcore/base64.zig
deleted file mode 100644
index aad1c471b..000000000
--- a/src/bun.js/webcore/base64.zig
+++ /dev/null
@@ -1,445 +0,0 @@
-// this is ripped from zig's stdlib
-const std = @import("std");
-const assert = std.debug.assert;
-const testing = std.testing;
-const mem = std.mem;
-
-pub const Error = error{
- InvalidCharacter,
- InvalidPadding,
- NoSpaceLeft,
-};
-
-/// Base64 codecs
-pub const Codecs = struct {
- alphabet_chars: [64]u8,
- pad_char: ?u8,
- decoderWithIgnore: fn (ignore: []const u8) Base64DecoderWithIgnore,
- Encoder: Base64Encoder,
- Decoder: Base64Decoder,
-};
-
-pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".*;
-fn standardBase64DecoderWithIgnore(ignore: []const u8) Base64DecoderWithIgnore {
- return Base64DecoderWithIgnore.init(standard_alphabet_chars, '=', ignore);
-}
-
-/// Standard Base64 codecs, with padding
-pub const standard = Codecs{
- .alphabet_chars = standard_alphabet_chars,
- .pad_char = '=',
- .decoderWithIgnore = standardBase64DecoderWithIgnore,
- .Encoder = Base64Encoder.init(standard_alphabet_chars, '='),
- .Decoder = Base64Decoder.init(standard_alphabet_chars, '='),
-};
-
-/// Standard Base64 codecs, without padding
-pub const standard_no_pad = Codecs{
- .alphabet_chars = standard_alphabet_chars,
- .pad_char = null,
- .decoderWithIgnore = standardBase64DecoderWithIgnore,
- .Encoder = Base64Encoder.init(standard_alphabet_chars, null),
- .Decoder = Base64Decoder.init(standard_alphabet_chars, null),
-};
-
-pub const url_safe_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*;
-fn urlSafeBase64DecoderWithIgnore(ignore: []const u8) Base64DecoderWithIgnore {
- return Base64DecoderWithIgnore.init(url_safe_alphabet_chars, null, ignore);
-}
-
-/// URL-safe Base64 codecs, with padding
-pub const url_safe = Codecs{
- .alphabet_chars = url_safe_alphabet_chars,
- .pad_char = '=',
- .decoderWithIgnore = urlSafeBase64DecoderWithIgnore,
- .Encoder = Base64Encoder.init(url_safe_alphabet_chars, '='),
- .Decoder = Base64Decoder.init(url_safe_alphabet_chars, '='),
-};
-
-/// URL-safe Base64 codecs, without padding
-pub const url_safe_no_pad = Codecs{
- .alphabet_chars = url_safe_alphabet_chars,
- .pad_char = null,
- .decoderWithIgnore = urlSafeBase64DecoderWithIgnore,
- .Encoder = Base64Encoder.init(url_safe_alphabet_chars, null),
- .Decoder = Base64Decoder.init(url_safe_alphabet_chars, null),
-};
-
-pub const standard_pad_char = @compileError("deprecated; use standard.pad_char");
-pub const standard_encoder = @compileError("deprecated; use standard.Encoder");
-pub const standard_decoder = @compileError("deprecated; use standard.Decoder");
-
-pub const Base64Encoder = struct {
- alphabet_chars: [64]u8,
- pad_char: ?u8,
-
- /// A bunch of assertions, then simply pass the data right through.
- pub fn init(alphabet_chars: [64]u8, pad_char: ?u8) Base64Encoder {
- assert(alphabet_chars.len == 64);
- var char_in_alphabet = [_]bool{false} ** 256;
- for (alphabet_chars) |c| {
- assert(!char_in_alphabet[c]);
- assert(pad_char == null or c != pad_char.?);
- char_in_alphabet[c] = true;
- }
- return Base64Encoder{
- .alphabet_chars = alphabet_chars,
- .pad_char = pad_char,
- };
- }
-
- /// Compute the encoded length
- pub fn calcSize(encoder: *const Base64Encoder, source_len: usize) usize {
- if (encoder.pad_char != null) {
- return @divTrunc(source_len + 2, 3) * 4;
- } else {
- const leftover = source_len % 3;
- return @divTrunc(source_len, 3) * 4 + @divTrunc(leftover * 4 + 2, 3);
- }
- }
-
- /// dest.len must at least be what you get from ::calcSize.
- pub fn encode(encoder: *const Base64Encoder, dest: []u8, source: []const u8) []const u8 {
- const out_len = encoder.calcSize(source.len);
- assert(dest.len >= out_len);
-
- var acc: u12 = 0;
- var acc_len: u4 = 0;
- var out_idx: usize = 0;
- for (source) |v| {
- acc = (acc << 8) + v;
- acc_len += 8;
- while (acc_len >= 6) {
- acc_len -= 6;
- dest[out_idx] = encoder.alphabet_chars[@truncate(u6, (acc >> acc_len))];
- out_idx += 1;
- }
- }
- if (acc_len > 0) {
- dest[out_idx] = encoder.alphabet_chars[@truncate(u6, (acc << 6 - acc_len))];
- out_idx += 1;
- }
- if (encoder.pad_char) |pad_char| {
- for (&dest[out_idx..]) |*pad| {
- pad.* = pad_char;
- }
- }
- return dest[0..out_len];
- }
-};
-
-pub const Base64Decoder = struct {
- const invalid_char: u8 = 0xff;
-
- /// e.g. 'A' => 0.
- /// `invalid_char` for any value not in the 64 alphabet chars.
- char_to_index: [256]u8,
- pad_char: ?u8,
-
- pub fn init(alphabet_chars: [64]u8, pad_char: ?u8) Base64Decoder {
- var result = Base64Decoder{
- .char_to_index = [_]u8{invalid_char} ** 256,
- .pad_char = pad_char,
- };
-
- var char_in_alphabet = [_]bool{false} ** 256;
- for (alphabet_chars, 0..) |c, i| {
- assert(!char_in_alphabet[c]);
- assert(pad_char == null or c != pad_char.?);
-
- result.char_to_index[c] = @intCast(u8, i);
- char_in_alphabet[c] = true;
- }
- return result;
- }
-
- /// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding.
- /// `InvalidPadding` is returned if the input length is not valid.
- pub fn calcSizeUpperBound(decoder: *const Base64Decoder, source_len: usize) Error!usize {
- var result = source_len / 4 * 3;
- const leftover = source_len % 4;
- if (decoder.pad_char != null) {
- if (leftover % 4 != 0) return error.InvalidPadding;
- } else {
- if (leftover % 4 == 1) return error.InvalidPadding;
- result += leftover * 3 / 4;
- }
- return result;
- }
-
- /// Return the exact decoded size for a slice.
- /// `InvalidPadding` is returned if the input length is not valid.
- pub fn calcSizeForSlice(decoder: *const Base64Decoder, source: []const u8) Error!usize {
- const source_len = source.len;
- var result = try decoder.calcSizeUpperBound(source_len);
- if (decoder.pad_char) |pad_char| {
- if (source_len >= 1 and source[source_len - 1] == pad_char) result -= 1;
- if (source_len >= 2 and source[source_len - 2] == pad_char) result -= 1;
- }
- return result;
- }
-
- /// dest.len must be what you get from ::calcSize.
- /// invalid characters result in error.InvalidCharacter.
- /// invalid padding results in error.InvalidPadding.
- pub fn decode(decoder: *const Base64Decoder, dest: []u8, source: []const u8) Error!void {
- if (decoder.pad_char != null and source.len % 4 != 0) return error.InvalidPadding;
- var acc: u12 = 0;
- var acc_len: u4 = 0;
- var dest_idx: usize = 0;
- var leftover_idx: ?usize = null;
- for (source, 0..) |c, src_idx| {
- const d = decoder.char_to_index[c];
- if (d == invalid_char) {
- if (decoder.pad_char == null or c != decoder.pad_char.?) return error.InvalidCharacter;
- leftover_idx = src_idx;
- break;
- }
- acc = (acc << 6) + d;
- acc_len += 6;
- if (acc_len >= 8) {
- acc_len -= 8;
- dest[dest_idx] = @truncate(u8, acc >> acc_len);
- dest_idx += 1;
- }
- }
- if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) {
- return error.InvalidPadding;
- }
- if (leftover_idx == null) return;
- var leftover = source[leftover_idx.?..];
- if (decoder.pad_char) |pad_char| {
- const padding_len = acc_len / 2;
- var padding_chars: usize = 0;
- for (leftover) |c| {
- if (c != pad_char) {
- return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
- }
- padding_chars += 1;
- }
- if (padding_chars != padding_len) return error.InvalidPadding;
- }
- }
-};
-
-pub const Base64DecoderWithIgnore = struct {
- decoder: Base64Decoder,
- char_is_ignored: [256]bool,
-
- pub fn init(alphabet_chars: [64]u8, pad_char: ?u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
- var result = Base64DecoderWithIgnore{
- .decoder = Base64Decoder.init(alphabet_chars, pad_char),
- .char_is_ignored = [_]bool{false} ** 256,
- };
- for (ignore_chars) |c| {
- assert(result.decoder.char_to_index[c] == Base64Decoder.invalid_char);
- assert(!result.char_is_ignored[c]);
- assert(result.decoder.pad_char != c);
- result.char_is_ignored[c] = true;
- }
- return result;
- }
-
- /// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding
- /// `InvalidPadding` is returned if the input length is not valid.
- pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) Error!usize {
- var result = source_len / 4 * 3;
- if (decoder_with_ignore.decoder.pad_char == null) {
- const leftover = source_len % 4;
- result += leftover * 3 / 4;
- }
- return result;
- }
-
- /// Invalid characters that are not ignored result in error.InvalidCharacter.
- /// Invalid padding results in error.InvalidPadding.
- /// Decoding more data than can fit in dest results in error.NoSpaceLeft. See also ::calcSizeUpperBound.
- /// Returns the number of bytes written to dest.
- pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8) Error!usize {
- const decoder = &decoder_with_ignore.decoder;
- var acc: u12 = 0;
- var acc_len: u4 = 0;
- var dest_idx: usize = 0;
- var leftover_idx: ?usize = null;
- for (source, 0..) |c, src_idx| {
- if (decoder_with_ignore.char_is_ignored[c]) continue;
- const d = decoder.char_to_index[c];
- if (d == Base64Decoder.invalid_char) {
- if (decoder.pad_char == null or c != decoder.pad_char.?) return error.InvalidCharacter;
- leftover_idx = src_idx;
- break;
- }
- acc = (acc << 6) + d;
- acc_len += 6;
- if (acc_len >= 8) {
- if (dest_idx == dest.len) return error.NoSpaceLeft;
- acc_len -= 8;
- dest[dest_idx] = @truncate(u8, acc >> acc_len);
- dest_idx += 1;
- }
- }
- if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) {
- return error.InvalidPadding;
- }
- const padding_len = acc_len / 2;
- if (leftover_idx == null) {
- if (decoder.pad_char != null and padding_len != 0) return error.InvalidPadding;
- return dest_idx;
- }
- var leftover = source[leftover_idx.?..];
- if (decoder.pad_char) |pad_char| {
- var padding_chars: usize = 0;
- for (leftover) |c| {
- if (decoder_with_ignore.char_is_ignored[c]) continue;
- if (c != pad_char) {
- return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
- }
- padding_chars += 1;
- }
- if (padding_chars != padding_len) return error.InvalidPadding;
- }
- return dest_idx;
- }
-};
-
-test "base64" {
- @setEvalBranchQuota(8000);
- try testBase64();
- comptime try testAllApis(standard, "comptime", "Y29tcHRpbWU=");
-}
-
-test "base64 url_safe_no_pad" {
- @setEvalBranchQuota(8000);
- try testBase64UrlSafeNoPad();
- comptime try testAllApis(url_safe_no_pad, "comptime", "Y29tcHRpbWU");
-}
-
-fn testBase64() !void {
- const codecs = standard;
-
- try testAllApis(codecs, "", "");
- try testAllApis(codecs, "f", "Zg==");
- try testAllApis(codecs, "fo", "Zm8=");
- try testAllApis(codecs, "foo", "Zm9v");
- try testAllApis(codecs, "foob", "Zm9vYg==");
- try testAllApis(codecs, "fooba", "Zm9vYmE=");
- try testAllApis(codecs, "foobar", "Zm9vYmFy");
-
- try testDecodeIgnoreSpace(codecs, "", " ");
- try testDecodeIgnoreSpace(codecs, "f", "Z g= =");
- try testDecodeIgnoreSpace(codecs, "fo", " Zm8=");
- try testDecodeIgnoreSpace(codecs, "foo", "Zm9v ");
- try testDecodeIgnoreSpace(codecs, "foob", "Zm9vYg = = ");
- try testDecodeIgnoreSpace(codecs, "fooba", "Zm9v YmE=");
- try testDecodeIgnoreSpace(codecs, "foobar", " Z m 9 v Y m F y ");
-
- // test getting some api errors
- try testError(codecs, "A", error.InvalidPadding);
- try testError(codecs, "AA", error.InvalidPadding);
- try testError(codecs, "AAA", error.InvalidPadding);
- try testError(codecs, "A..A", error.InvalidCharacter);
- try testError(codecs, "AA=A", error.InvalidPadding);
- try testError(codecs, "AA/=", error.InvalidPadding);
- try testError(codecs, "A/==", error.InvalidPadding);
- try testError(codecs, "A===", error.InvalidPadding);
- try testError(codecs, "====", error.InvalidPadding);
-
- try testNoSpaceLeftError(codecs, "AA==");
- try testNoSpaceLeftError(codecs, "AAA=");
- try testNoSpaceLeftError(codecs, "AAAA");
- try testNoSpaceLeftError(codecs, "AAAAAA==");
-}
-
-fn testBase64UrlSafeNoPad() !void {
- const codecs = url_safe_no_pad;
-
- try testAllApis(codecs, "", "");
- try testAllApis(codecs, "f", "Zg");
- try testAllApis(codecs, "fo", "Zm8");
- try testAllApis(codecs, "foo", "Zm9v");
- try testAllApis(codecs, "foob", "Zm9vYg");
- try testAllApis(codecs, "fooba", "Zm9vYmE");
- try testAllApis(codecs, "foobar", "Zm9vYmFy");
-
- try testDecodeIgnoreSpace(codecs, "", " ");
- try testDecodeIgnoreSpace(codecs, "f", "Z g ");
- try testDecodeIgnoreSpace(codecs, "fo", " Zm8");
- try testDecodeIgnoreSpace(codecs, "foo", "Zm9v ");
- try testDecodeIgnoreSpace(codecs, "foob", "Zm9vYg ");
- try testDecodeIgnoreSpace(codecs, "fooba", "Zm9v YmE");
- try testDecodeIgnoreSpace(codecs, "foobar", " Z m 9 v Y m F y ");
-
- // test getting some api errors
- try testError(codecs, "A", error.InvalidPadding);
- try testError(codecs, "AAA=", error.InvalidCharacter);
- try testError(codecs, "A..A", error.InvalidCharacter);
- try testError(codecs, "AA=A", error.InvalidCharacter);
- try testError(codecs, "AA/=", error.InvalidCharacter);
- try testError(codecs, "A/==", error.InvalidCharacter);
- try testError(codecs, "A===", error.InvalidCharacter);
- try testError(codecs, "====", error.InvalidCharacter);
-
- try testNoSpaceLeftError(codecs, "AA");
- try testNoSpaceLeftError(codecs, "AAA");
- try testNoSpaceLeftError(codecs, "AAAA");
- try testNoSpaceLeftError(codecs, "AAAAAA");
-}
-
-fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: []const u8) !void {
- // Base64Encoder
- {
- var buffer: [0x100]u8 = undefined;
- const encoded = codecs.Encoder.encode(&buffer, expected_decoded);
- try testing.expectEqualSlices(u8, expected_encoded, encoded);
- }
-
- // Base64Decoder
- {
- var buffer: [0x100]u8 = undefined;
- var decoded = buffer[0..try codecs.Decoder.calcSizeForSlice(expected_encoded)];
- try codecs.Decoder.decode(decoded, expected_encoded);
- try testing.expectEqualSlices(u8, expected_decoded, decoded);
- }
-
- // Base64DecoderWithIgnore
- {
- const decoder_ignore_nothing = codecs.decoderWithIgnore("");
- var buffer: [0x100]u8 = undefined;
- var decoded = buffer[0..try decoder_ignore_nothing.calcSizeUpperBound(expected_encoded.len)];
- var written = try decoder_ignore_nothing.decode(decoded, expected_encoded);
- try testing.expect(written <= decoded.len);
- try testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
- }
-}
-
-fn testDecodeIgnoreSpace(codecs: Codecs, expected_decoded: []const u8, encoded: []const u8) !void {
- const decoder_ignore_space = codecs.decoderWithIgnore(" ");
- var buffer: [0x100]u8 = undefined;
- var decoded = buffer[0..try decoder_ignore_space.calcSizeUpperBound(encoded.len)];
- var written = try decoder_ignore_space.decode(decoded, encoded);
- try testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
-}
-
-fn testError(codecs: Codecs, encoded: []const u8, expected_err: anyerror) !void {
- const decoder_ignore_space = codecs.decoderWithIgnore(" ");
- var buffer: [0x100]u8 = undefined;
- if (codecs.Decoder.calcSizeForSlice(encoded)) |decoded_size| {
- var decoded = buffer[0..decoded_size];
- if (codecs.Decoder.decode(decoded, encoded)) |_| {
- return error.ExpectedError;
- } else |err| if (err != expected_err) return err;
- } else |err| if (err != expected_err) return err;
-
- if (decoder_ignore_space.decode(buffer[0..], encoded)) |_| {
- return error.ExpectedError;
- } else |err| if (err != expected_err) return err;
-}
-
-fn testNoSpaceLeftError(codecs: Codecs, encoded: []const u8) !void {
- const decoder_ignore_space = codecs.decoderWithIgnore(" ");
- var buffer: [0x100]u8 = undefined;
- var decoded = buffer[0 .. (try codecs.Decoder.calcSizeForSlice(encoded)) - 1];
- if (decoder_ignore_space.decode(decoded, encoded)) |_| {
- return error.ExpectedError;
- } else |err| if (err != error.NoSpaceLeft) return err;
-}
diff --git a/src/bun.js/webcore/body.zig b/src/bun.js/webcore/body.zig
index 97c9f7874..d4bd490c1 100644
--- a/src/bun.js/webcore/body.zig
+++ b/src/bun.js/webcore/body.zig
@@ -477,6 +477,7 @@ pub const Body = struct {
// blob.bytes[0..blob.bytes.len],
// []const u16,
// str.utf16SliceAligned(),
+ // true,
// );
// blob.len = @intCast(InlineBlob.IntSize, result.written);
// std.debug.assert(@as(usize, result.read) == str.len);
diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig
index deab624d0..d58513c1e 100644
--- a/src/bun.js/webcore/encoding.zig
+++ b/src/bun.js/webcore/encoding.zig
@@ -98,7 +98,7 @@ pub const TextEncoder = struct {
// max utf16 -> utf8 length
if (slice.len <= buf.len / 4) {
- const result = strings.copyUTF16IntoUTF8(&buf, @TypeOf(slice), slice);
+ const result = strings.copyUTF16IntoUTF8(&buf, @TypeOf(slice), slice, true);
if (result.read == 0 or result.written == 0) {
const uint8array = JSC.JSValue.createUninitializedUint8Array(globalThis, 3);
const array_buffer = uint8array.asArrayBuffer(globalThis).?;
@@ -221,7 +221,7 @@ pub const TextEncoder = struct {
) u64 {
var output = buf_ptr[0..buf_len];
const input = input_ptr[0..input_len];
- const result: strings.EncodeIntoResult = strings.copyUTF16IntoUTF8(output, []const u16, input);
+ const result: strings.EncodeIntoResult = strings.copyUTF16IntoUTF8(output, []const u16, input, true);
if (result.read == 0 or result.written == 0) {
const replacement_char = [_]u8{ 239, 191, 189 };
@memcpy(buf_ptr, &replacement_char, replacement_char.len);
@@ -683,7 +683,7 @@ pub const TextDecoder = struct {
};
pub const Encoder = struct {
- export fn Bun__encoding__writeLatin1(input: [*]const u8, len: usize, to: [*]u8, to_len: usize, encoding: u8) i64 {
+ export fn Bun__encoding__writeLatin1(input: [*]const u8, len: usize, to: [*]u8, to_len: usize, encoding: u8) usize {
return switch (@intToEnum(JSC.Node.Encoding, encoding)) {
.utf8 => writeU8(input, len, to, to_len, .utf8),
.latin1 => writeU8(input, len, to, to_len, .ascii),
@@ -694,9 +694,9 @@ pub const Encoder = struct {
.base64url => writeU8(input, len, to, to_len, .base64url),
.hex => writeU8(input, len, to, to_len, .hex),
else => unreachable,
- };
+ } catch 0;
}
- export fn Bun__encoding__writeUTF16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, encoding: u8) i64 {
+ export fn Bun__encoding__writeUTF16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, encoding: u8) usize {
return switch (@intToEnum(JSC.Node.Encoding, encoding)) {
.utf8 => writeU16(input, len, to, to_len, .utf8, false),
.latin1 => writeU16(input, len, to, to_len, .ascii, false),
@@ -707,7 +707,7 @@ pub const Encoder = struct {
.base64url => writeU16(input, len, to, to_len, .base64url, false),
.hex => writeU16(input, len, to, to_len, .hex, false),
else => unreachable,
- };
+ } catch 0;
}
export fn Bun__encoding__byteLengthLatin1(input: [*]const u8, len: usize, encoding: u8) usize {
return switch (@intToEnum(JSC.Node.Encoding, encoding)) {
@@ -783,7 +783,7 @@ pub const Encoder = struct {
}
// pub fn writeUTF16AsUTF8(utf16: [*]const u16, len: usize, to: [*]u8, to_len: usize) callconv(.C) i32 {
- // return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, utf16[0..len]).written);
+ // return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, utf16[0..len], true).written);
// }
pub fn toString(input_ptr: [*]const u8, len: usize, global: *JSGlobalObject, comptime encoding: JSC.Node.Encoding) JSValue {
@@ -839,7 +839,7 @@ pub const Encoder = struct {
return ZigString.toExternalU16(output.ptr, output.len, global);
},
- JSC.Node.Encoding.hex => {
+ .hex => {
var output = allocator.alloc(u8, input.len * 2) catch return ZigString.init("Out of memory").toErrorInstance(global);
const wrote = strings.encodeBytesToHex(output, input);
std.debug.assert(wrote == output.len);
@@ -848,11 +848,11 @@ pub const Encoder = struct {
return val.toExternalValue(global);
},
- JSC.Node.Encoding.base64url => {
+ .base64url => {
return JSC.WTF.toBase64URLStringValue(input, global);
},
- JSC.Node.Encoding.base64 => {
+ .base64 => {
const to_len = bun.base64.encodeLen(input);
var to = allocator.alloc(u8, to_len) catch return ZigString.init("Out of memory").toErrorInstance(global);
const wrote = bun.base64.encode(to, input);
@@ -861,7 +861,7 @@ pub const Encoder = struct {
}
}
- pub fn writeU8(input: [*]const u8, len: usize, to_ptr: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding) i64 {
+ pub fn writeU8(input: [*]const u8, len: usize, to_ptr: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding) !usize {
if (len == 0 or to_len == 0)
return 0;
@@ -873,11 +873,11 @@ pub const Encoder = struct {
// if (comptime encoding.isBinaryToText()) {}
switch (comptime encoding) {
- JSC.Node.Encoding.buffer => {
+ .buffer => {
const written = @min(len, to_len);
@memcpy(to_ptr, input, written);
- return @intCast(i64, written);
+ return written;
},
.latin1, .ascii => {
const written = @min(len, to_len);
@@ -891,14 +891,14 @@ pub const Encoder = struct {
strings.copyLatin1IntoASCII(to, remain);
}
- return @intCast(i64, written);
+ return written;
},
.utf8 => {
// need to encode
- return @intCast(i64, strings.copyLatin1IntoUTF8(to_ptr[0..to_len], []const u8, input[0..len]).written);
+ return strings.copyLatin1IntoUTF8(to_ptr[0..to_len], []const u8, input[0..len]).written;
},
// encode latin1 into UTF16
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
if (to_len < 2)
return 0;
@@ -917,29 +917,13 @@ pub const Encoder = struct {
}
},
- JSC.Node.Encoding.hex => {
- return @intCast(i64, strings.decodeHexToBytes(to_ptr[0..to_len], u8, input[0..len]));
- },
-
- 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;
-
- if (strings.endsWithComptime(slice, "==")) {
- slice = slice[0 .. slice.len - 2];
- } else if (slice[slice.len - 1] == '=') {
- slice = slice[0 .. slice.len - 1];
- }
-
- const wrote = bun.base64.decodeURLSafe(to_ptr[0..to_len], slice).written;
- return @intCast(i64, wrote);
+ .hex => {
+ return strings.decodeHexToBytes(to_ptr[0..to_len], u8, input[0..len]);
},
- JSC.Node.Encoding.base64 => {
- return @intCast(i64, bun.base64.decode(to_ptr[0..to_len], input[0..len]).written);
+ .base64, .base64url => {
+ return bun.base64.decode(to_ptr[0..to_len], input[0..len]).written;
},
- // else => return 0,
}
}
@@ -952,46 +936,46 @@ pub const Encoder = struct {
return strings.elementLengthLatin1IntoUTF8([]const u8, input[0..len]);
},
- .latin1, JSC.Node.Encoding.ascii, JSC.Node.Encoding.buffer => {
+ .latin1, .ascii, .buffer => {
return len;
},
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
return strings.elementLengthUTF8IntoUTF16([]const u8, input[0..len]) * 2;
},
- JSC.Node.Encoding.hex => {
+ .hex => {
return len / 2;
},
- JSC.Node.Encoding.base64, JSC.Node.Encoding.base64url => {
+ .base64, .base64url => {
return bun.base64.decodeLen(input[0..len]);
},
// else => return &[_]u8{};
}
}
- pub fn writeU16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding, comptime allow_partial_write: bool) i64 {
+ pub fn writeU16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding, comptime allow_partial_write: bool) !usize {
if (len == 0)
return 0;
switch (comptime encoding) {
.utf8 => {
- return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, input[0..len]).written);
+ return strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, input[0..len], allow_partial_write).written;
},
- .latin1, JSC.Node.Encoding.ascii, JSC.Node.Encoding.buffer => {
+ .latin1, .ascii, .buffer => {
const out = @min(len, to_len);
strings.copyU16IntoU8(to[0..to_len], []const u16, input[0..out]);
- return @intCast(i64, out);
+ return out;
},
// string is already encoded, just need to copy the data
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
if (allow_partial_write) {
const bytes_input_len = len * 2;
const written = @min(bytes_input_len, to_len);
const input_u8 = @ptrCast([*]const u8, input);
strings.copyU16IntoU8(to[0..written], []const u8, input_u8[0..written]);
- return @intCast(i64, written);
+ return written;
} else {
const bytes_input_len = len * 2;
const written = @min(bytes_input_len, to_len);
@@ -1000,15 +984,15 @@ pub const Encoder = struct {
const fixed_len = (written / 2) * 2;
const input_u8 = @ptrCast([*]const u8, input);
strings.copyU16IntoU8(to[0..written], []const u8, input_u8[0..fixed_len]);
- return @intCast(i64, fixed_len);
+ return fixed_len;
}
},
- JSC.Node.Encoding.hex => {
- return @intCast(i64, strings.decodeHexToBytes(to[0..to_len], u16, input[0..len]));
+ .hex => {
+ return strings.decodeHexToBytes(to[0..to_len], u16, input[0..len]);
},
- JSC.Node.Encoding.base64, JSC.Node.Encoding.base64url => {
+ .base64, .base64url => {
if (to_len < 2 or len == 0)
return 0;
@@ -1033,15 +1017,15 @@ pub const Encoder = struct {
.ascii, .latin1, .utf8 => {
return strings.elementLengthUTF16IntoUTF8([]const u16, input[0..len]);
},
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.buffer, JSC.Node.Encoding.utf16le => {
+ .ucs2, .buffer, .utf16le => {
return len * 2;
},
- JSC.Node.Encoding.hex => {
+ .hex => {
return len / 2;
},
- JSC.Node.Encoding.base64, JSC.Node.Encoding.base64url => {
+ .base64, .base64url => {
return bun.base64.decodeLenUpperBound(len);
},
// else => return &[_]u8{};
@@ -1057,13 +1041,12 @@ pub const Encoder = struct {
}
pub fn constructFromU8(input: [*]const u8, len: usize, comptime encoding: JSC.Node.Encoding) []u8 {
- if (len == 0)
- return &[_]u8{};
+ if (len == 0) return &[_]u8{};
const allocator = VirtualMachine.get().allocator;
switch (comptime encoding) {
- JSC.Node.Encoding.buffer => {
+ .buffer => {
var to = allocator.alloc(u8, len) catch return &[_]u8{};
@memcpy(to.ptr, input, len);
@@ -1082,52 +1065,35 @@ pub const Encoder = struct {
},
// encode latin1 into UTF16
// return as bytes
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
var to = allocator.alloc(u16, len) catch return &[_]u8{};
_ = strings.copyLatin1IntoUTF16([]u16, to, []const u8, input[0..len]);
return std.mem.sliceAsBytes(to[0..len]);
},
- JSC.Node.Encoding.hex => {
+ .hex => {
if (len < 2)
return &[_]u8{};
var to = allocator.alloc(u8, len / 2) catch return &[_]u8{};
- return to[0..strings.decodeHexToBytes(to, u8, input[0..len])];
+ return to[0..strings.decodeHexToBytesTruncate(to, u8, input[0..len])];
},
- 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 &[_]u8{};
+ .base64, .base64url => {
+ const slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.vt});
+ if (slice.len == 0) return &[_]u8{};
- if (strings.endsWithComptime(slice, "==")) {
- slice = slice[0 .. slice.len - 2];
- } else if (slice[slice.len - 1] == '=') {
- slice = slice[0 .. slice.len - 1];
- }
+ const outlen = bun.base64.decodeLen(slice);
+ const to = allocator.alloc(u8, outlen) catch return &[_]u8{};
- const to_len = bun.base64.urlsafe.decoder.calcSizeForSlice(slice) catch unreachable;
- var to = allocator.alloc(u8, to_len) catch return &[_]u8{};
- const wrote = bun.base64.decodeURLSafe(to[0..to_len], slice).written;
+ const wrote = bun.base64.decode(to[0..outlen], slice).written;
return to[0..wrote];
},
-
- JSC.Node.Encoding.base64 => {
- var slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.vt});
- var outlen = bun.base64.decodeLen(slice);
-
- var to = allocator.alloc(u8, outlen) catch return &[_]u8{};
- const written = bun.base64.decode(to[0..outlen], slice).written;
- return to[0..@min(written, outlen)];
- },
- // else => return 0,
}
}
pub fn constructFromU16(input: [*]const u16, len: usize, comptime encoding: JSC.Node.Encoding) []u8 {
- if (len == 0)
- return &[_]u8{};
+ if (len == 0) return &[_]u8{};
const allocator = VirtualMachine.get().allocator;
@@ -1135,7 +1101,7 @@ pub const Encoder = struct {
.utf8 => {
return strings.toUTF8AllocWithType(allocator, []const u16, input[0..len]) catch return &[_]u8{};
},
- JSC.Node.Encoding.latin1, JSC.Node.Encoding.buffer, JSC.Node.Encoding.ascii => {
+ .latin1, .buffer, .ascii => {
var to = allocator.alloc(u8, len) catch return &[_]u8{};
var input_bytes = std.mem.sliceAsBytes(input[0..len]);
@memcpy(to.ptr, input_bytes.ptr, input_bytes.len);
@@ -1146,34 +1112,24 @@ pub const Encoder = struct {
return to;
},
// string is already encoded, just need to copy the data
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
var to = std.mem.sliceAsBytes(allocator.alloc(u16, len * 2) catch return &[_]u8{});
@memcpy(to.ptr, std.mem.sliceAsBytes(input[0..len]).ptr, std.mem.sliceAsBytes(input[0..len]).len);
return to;
},
- JSC.Node.Encoding.hex => {
+ .hex => {
var to = allocator.alloc(u8, len * 2) catch return &[_]u8{};
- return to[0..strings.decodeHexToBytes(to, u16, input[0..len])];
+ return to[0..strings.decodeHexToBytesTruncate(to, u16, input[0..len])];
},
- JSC.Node.Encoding.base64 => {
- // very very slow case!
- // shouldn't really happen though
- var transcoded = strings.toUTF8Alloc(allocator, input[0..len]) catch return &[_]u8{};
- defer allocator.free(transcoded);
- return constructFromU8(transcoded.ptr, transcoded.len, .base64);
- },
-
- JSC.Node.Encoding.base64url => {
-
+ .base64, .base64url => {
// very very slow case!
// shouldn't really happen though
var transcoded = strings.toUTF8Alloc(allocator, input[0..len]) catch return &[_]u8{};
defer allocator.free(transcoded);
- return constructFromU8(transcoded.ptr, transcoded.len, .base64url);
+ return constructFromU8(transcoded.ptr, transcoded.len, encoding);
},
- // else => return 0,
}
}
diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig
index 1de209b69..748b4583c 100644
--- a/src/bun.js/webcore/streams.zig
+++ b/src/bun.js/webcore/streams.zig
@@ -983,7 +983,7 @@ pub const Sink = struct {
if (stack_size >= str.len * 2) {
var buf: [stack_size]u8 = undefined;
- const copied = strings.copyUTF16IntoUTF8(&buf, []const u16, str);
+ const copied = strings.copyUTF16IntoUTF8(&buf, []const u16, str, true);
std.debug.assert(copied.written <= stack_size);
std.debug.assert(copied.read <= stack_size);
if (input.isDone()) {
diff --git a/src/http/websocket_http_client.zig b/src/http/websocket_http_client.zig
index a4f9284d3..a5be7faab 100644
--- a/src/http/websocket_http_client.zig
+++ b/src/http/websocket_http_client.zig
@@ -776,7 +776,7 @@ const Copy = union(enum) {
switch (this) {
.utf16 => |utf16| {
header.len = WebsocketHeader.packLength(content_byte_len);
- const encode_into_result = strings.copyUTF16IntoUTF8(to_mask, []const u16, utf16);
+ const encode_into_result = strings.copyUTF16IntoUTF8(to_mask, []const u16, utf16, true);
std.debug.assert(@as(usize, encode_into_result.written) == content_byte_len);
std.debug.assert(@as(usize, encode_into_result.read) == utf16.len);
header.len = WebsocketHeader.packLength(encode_into_result.written);
diff --git a/src/napi/napi.zig b/src/napi/napi.zig
index b06e25d7e..99d7c82fb 100644
--- a/src/napi/napi.zig
+++ b/src/napi/napi.zig
@@ -384,11 +384,8 @@ pub export fn napi_get_value_string_latin1(env: napi_env, value: napi_value, buf
if (zig_str.is16Bit()) {
const utf16 = zig_str.utf16SliceAligned();
- const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, buf_.len, .latin1, false);
- if (wrote < 0) {
- return genericFailure();
- }
- maybeAppendNull(&buf[@intCast(usize, wrote)], bufsize == 0);
+ const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, buf_.len, .latin1, false) catch return genericFailure();
+ maybeAppendNull(&buf[wrote], bufsize == 0);
// if zero terminated, report the length of the string without the null
result.* = @intCast(@TypeOf(result.*), wrote);
return .ok;
@@ -448,11 +445,8 @@ pub export fn napi_get_value_string_utf8(env: napi_env, value: napi_value, buf_p
if (zig_str.is16Bit()) {
const utf16 = zig_str.utf16SliceAligned();
- const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, buf_.len, .utf8, false);
- if (wrote < 0) {
- return genericFailure();
- }
- buf[@intCast(usize, wrote)] = 0;
+ const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, buf_.len, .utf8, false) catch return genericFailure();
+ buf[wrote] = 0;
if (result_ptr) |result| {
result.* = @intCast(@TypeOf(result.*), wrote);
}
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index e85fc4ef8..7bdd7cfe5 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -2550,7 +2550,7 @@ pub fn latin1ToCodepointBytesAssumeNotASCII16(char: u32) u16 {
return latin1_to_utf16_conversion_table[@truncate(u8, char)];
}
-pub fn copyUTF16IntoUTF8(buf: []u8, comptime Type: type, utf16: Type) EncodeIntoResult {
+pub fn copyUTF16IntoUTF8(buf: []u8, comptime Type: type, utf16: Type, comptime allow_partial_write: bool) EncodeIntoResult {
if (comptime Type == []const u16) {
if (bun.FeatureFlags.use_simdutf) {
if (utf16.len == 0)
@@ -2564,14 +2564,14 @@ pub fn copyUTF16IntoUTF8(buf: []u8, comptime Type: type, utf16: Type) EncodeInto
else
buf.len;
- return copyUTF16IntoUTF8WithBuffer(buf, Type, utf16, trimmed, out_len);
+ return copyUTF16IntoUTF8WithBuffer(buf, Type, utf16, trimmed, out_len, allow_partial_write);
}
}
- return copyUTF16IntoUTF8WithBuffer(buf, Type, utf16, utf16, utf16.len);
+ return copyUTF16IntoUTF8WithBuffer(buf, Type, utf16, utf16, utf16.len, allow_partial_write);
}
-pub fn copyUTF16IntoUTF8WithBuffer(buf: []u8, comptime Type: type, utf16: Type, trimmed: Type, out_len: usize) EncodeIntoResult {
+pub fn copyUTF16IntoUTF8WithBuffer(buf: []u8, comptime Type: type, utf16: Type, trimmed: Type, out_len: usize, comptime allow_partial_write: bool) EncodeIntoResult {
var remaining = buf;
var utf16_remaining = utf16;
var ended_on_non_ascii = false;
@@ -2604,7 +2604,7 @@ pub fn copyUTF16IntoUTF8WithBuffer(buf: []u8, comptime Type: type, utf16: Type,
const width: usize = replacement.utf8Width();
if (width > remaining.len) {
ended_on_non_ascii = width > 1;
- switch (width) {
+ if (comptime allow_partial_write) switch (width) {
2 => {
if (remaining.len > 0) {
//only first will be written
@@ -2650,7 +2650,7 @@ pub fn copyUTF16IntoUTF8WithBuffer(buf: []u8, comptime Type: type, utf16: Type,
},
else => {},
- }
+ };
break;
}
@@ -3257,8 +3257,9 @@ pub fn indexOfNotChar(slice: []const u8, char: u8) ?u32 {
return null;
}
+const invalid_char: u8 = 0xff;
const hex_table: [255]u8 = brk: {
- var values: [255]u8 = [_]u8{0} ** 255;
+ var values: [255]u8 = [_]u8{invalid_char} ** 255;
values['0'] = 0;
values['1'] = 1;
values['2'] = 2;
@@ -3285,22 +3286,41 @@ const hex_table: [255]u8 = brk: {
break :brk values;
};
-pub fn decodeHexToBytes(destination: []u8, comptime Char: type, source: []const Char) usize {
+pub fn decodeHexToBytes(destination: []u8, comptime Char: type, source: []const Char) !usize {
+ return _decodeHexToBytes(destination, Char, source, false);
+}
+
+pub fn decodeHexToBytesTruncate(destination: []u8, comptime Char: type, source: []const Char) usize {
+ return _decodeHexToBytes(destination, Char, source, true) catch 0;
+}
+
+inline fn _decodeHexToBytes(destination: []u8, comptime Char: type, source: []const Char, comptime truncate: bool) !usize {
var remain = destination;
var input = source;
- while (input.len > 1 and remain.len > 0) {
+ while (remain.len > 0 and input.len > 1) {
const int = input[0..2].*;
+ if (comptime @sizeOf(Char) > 1) {
+ if (int[0] > std.math.maxInt(u8) or int[1] > std.math.maxInt(u8)) {
+ if (comptime truncate) break;
+ return error.InvalidByteSequence;
+ }
+ }
const a = hex_table[@truncate(u8, int[0])];
const b = hex_table[@truncate(u8, int[1])];
- if (a == 255 or b == 255) {
- break;
+ if (a == invalid_char or b == invalid_char) {
+ if (comptime truncate) break;
+ return error.InvalidByteSequence;
}
remain[0] = a << 4 | b;
remain = remain[1..];
input = input[2..];
}
+ if (comptime !truncate) {
+ if (remain.len > 0 and input.len > 0) return error.InvalidByteSequence;
+ }
+
return destination.len - remain.len;
}
@@ -3615,7 +3635,7 @@ pub fn formatUTF16Type(comptime Slice: type, slice_: Slice, writer: anytype) !vo
var slice = slice_;
while (slice.len > 0) {
- const result = strings.copyUTF16IntoUTF8(chunk, Slice, slice);
+ const result = strings.copyUTF16IntoUTF8(chunk, Slice, slice, true);
if (result.read == 0 or result.written == 0)
break;
try writer.writeAll(chunk[0..result.written]);
diff --git a/src/string_mutable.zig b/src/string_mutable.zig
index d7b0cf930..129ea1481 100644
--- a/src/string_mutable.zig
+++ b/src/string_mutable.zig
@@ -327,6 +327,7 @@ pub const MutableString = struct {
this.remain()[0 .. bytes.len * 2],
[]const u16,
bytes,
+ true,
);
this.context.list.items.len += @as(usize, decoded.written);
return pending.len;
@@ -340,6 +341,7 @@ pub const MutableString = struct {
this.remain()[0 .. bytes.len * 2],
[]const u16,
bytes,
+ true,
);
this.pos += @as(usize, decoded.written);
}